diff --git a/bundle.json b/bundle.json index ded14f6a75e1871877a533a53154379aa192f90d..374976e19b6bd8d1cb760ab5a648ea844d723ecd 100644 --- a/bundle.json +++ b/bundle.json @@ -20,7 +20,8 @@ "SystemCapability.FileManagement.File.Environment.FolderObtain" ], "features": [ - "file_api_read_optimize" + "file_api_read_optimize", + "file_api_feature_inner_hyperaio" ], "adapted_system_type": [ "mini","small","standard" ], "rom": "4096KB", @@ -45,7 +46,8 @@ "napi", "samgr", "app_file_service", - "os_account" + "os_account", + "liburing" ], "third_party": [ "e2fsprogs", @@ -59,7 +61,8 @@ "//foundation/filemanagement/file_api/interfaces/kits/js:build_kits_js", "//foundation/filemanagement/file_api/interfaces/kits/ts/streamrw:streamrw_packages", "//foundation/filemanagement/file_api/interfaces/kits/ts/streamhash:streamhash_packages", - "//foundation/filemanagement/file_api/interfaces/kits/cj:fs_ffi_packages" + "//foundation/filemanagement/file_api/interfaces/kits/cj:fs_ffi_packages", + "//foundation/filemanagement/file_api/interfaces/kits/hyperaio:group_hyperaio" ], "service_group": [] }, @@ -73,6 +76,15 @@ "header_base": "//foundation/filemanagement/file_api/interfaces/kits/native/remote_uri" } }, + { + "name": "//foundation/filemanagement/file_api/interfaces/kits/hyperaio:HyperAio", + "header": { + "header_files": [ + "hyperaio.h" + ], + "header_base": "//foundation/filemanagement/file_api/interfaces/kits/hyperaio/include" + } + }, { "name": "//foundation/filemanagement/file_api/interfaces/kits/native:environment_native", "header": { diff --git a/file_api.gni b/file_api.gni index 16a2906232aa9e6c0be06d10d274a6f673b32e2e..e002ea9f62528a6303a10106c55951a2d083ca31 100644 --- a/file_api.gni +++ b/file_api.gni @@ -26,4 +26,5 @@ use_mingw_win = "${current_os}_${current_cpu}" == "mingw_x86_64" declare_args() { file_api_read_optimize = false + file_api_feature_inner_hyperaio = false } diff --git a/interfaces/kits/hyperaio/BUILD.gn b/interfaces/kits/hyperaio/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..c4cfa01d5c7323fe0320dc0421cf8524f7b73384 --- /dev/null +++ b/interfaces/kits/hyperaio/BUILD.gn @@ -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. + +import("//build/ohos.gni") +import("//foundation/filemanagement/file_api/file_api.gni") + +group("group_hyperaio") { + deps = [ ] + if (file_api_feature_inner_hyperaio) { + deps += [ ":HyperAio" ] + } +} + +config("hyperaio_config") { + visibility = [ ":*" ] + include_dirs = [ "include" ] +} + +ohos_shared_library("HyperAio") { + if (!use_mingw_win && !use_mac) { + cflags = [ + "-fdata-sections", + "-ffunction-sections", + "-Oz", + ] + cflags_cc = [ + "-fvisibility-inlines-hidden", + "-Oz", + ] + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + } + + sources = [ + "src/hyperaio.cpp", + "src/hyperaio_trace.cpp" + ] + + public_configs = [ ":hyperaio_config" ] + + deps = [ ] + + external_deps = [ + "c_utils:utils", + "liburing:liburing", + "ipc:ipc_core", + "access_token:libaccesstoken_sdk", + "hitrace:hitrace_meter", + ] + if (file_api_feature_inner_hyperaio) { + external_deps += [ "hilog:libhilog" ] + } + install_images = [ "system" ] + part_name = "file_api" + subsystem_name = "filemanagement" + if (file_api_feature_inner_hyperaio) { + defines = [ "HYPERAIO_USE_LIBURING" ] + } +} \ No newline at end of file diff --git a/interfaces/kits/hyperaio/include/hyperaio.h b/interfaces/kits/hyperaio/include/hyperaio.h new file mode 100644 index 0000000000000000000000000000000000000000..9977b8c160d18fc59a32aeb9375df7a64074883b --- /dev/null +++ b/interfaces/kits/hyperaio/include/hyperaio.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FILEMANAGEMENT_FILE_API_INTERFACES_KITS_IOURING_HYPER_AIO_H +#define FILEMANAGEMENT_FILE_API_INTERFACES_KITS_IOURING_HYPER_AIO_H + +#include +#include +#ifdef HYPERAIO_USE_LIBURING +#include "liburing.h" +#endif +namespace OHOS { +namespace HyperAio { +#define HYPERAIO_APP_PERMISSION (1U << 0) +#ifndef EOK +#define EOK (0) +#endif + +struct ReadInfo { + int32_t fd; + uint32_t len; + uint64_t offset; + void *buf; + uint64_t userData; +}; + +struct ReadReqs { + uint32_t reqNum; + struct ReadInfo *reqs; +}; + +struct OpenInfo { + int32_t dfd; + int32_t flags; + mode_t mode; + void *path; + uint64_t userData; +}; + +struct OpenReqs { + uint32_t reqNum; + struct OpenInfo *reqs; +}; + +struct CancelInfo { + uint64_t userData; + uint64_t targetUserData; +}; + +struct CancelReqs { + uint32_t reqNum; + struct CancelInfo *reqs; +}; + +struct IoResponse { + uint64_t userData; + int32_t res; + uint32_t flags; + IoResponse(uint64_t userData, int32_t res, uint32_t flags) + : userData(userData), + res(res), + flags(flags) { + } +}; + +class HyperAio { +public: + using ProcessIoResultCallBack = std::function)>; + uint32_t SupportIouring(); + int32_t CtxInit(ProcessIoResultCallBack *callBack); + int32_t StartReadReqs(ReadReqs *req); + int32_t StartOpenReqs(OpenReqs *req); + int32_t StartCancelReqs(CancelReqs *req); + int32_t DestroyCtx(); +private: + ProcessIoResultCallBack ioResultCallBack_ = nullptr; +#ifdef HYPERAIO_USE_LIBURING + io_uring uring_; + std::thread harvestThread_; + std::atomic stopThread_; + std::atomic initialized_; + void HarvestRes(); + struct io_uring_sqe* GetSqeWithRetry(struct io_uring *ring); +#endif +}; +} +} +#endif \ No newline at end of file diff --git a/interfaces/kits/hyperaio/include/hyperaio_trace.h b/interfaces/kits/hyperaio/include/hyperaio_trace.h new file mode 100644 index 0000000000000000000000000000000000000000..0ea6dbc778d90a8d77897aa40d9236cb456b941d --- /dev/null +++ b/interfaces/kits/hyperaio/include/hyperaio_trace.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 HYPERAIO_TRACE_H +#define HYPERAIO_TRACE_H + +#include "hitrace_meter.h" +#include "libhilog.h" + +namespace OHOS { +namespace HyperAio { + +class HyperaioTrace { +public: + HyperaioTrace(const std::string& value, bool isShowLog = false); + ~HyperaioTrace(); + void End(); +private: + std::string value_; + bool isFinished_{false}; +}; +} // namespace HyperAio +} // namespace OHOS + +#endif //HYPERAIO_TRACE_H \ No newline at end of file diff --git a/interfaces/kits/hyperaio/include/libhilog.h b/interfaces/kits/hyperaio/include/libhilog.h new file mode 100644 index 0000000000000000000000000000000000000000..3535112a2d2ae8577ecbbbe46ac3b053e1b52e6b --- /dev/null +++ b/interfaces/kits/hyperaio/include/libhilog.h @@ -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. + */ + +#ifndef HYPERAIO_LIBHILOG_H +#define HYPERAIO_LIBHILOG_H + +#include "hilog/log.h" + +#include + +namespace OHOS { +namespace HyperAio { + +#if defined __FILE_NAME__ +#define FILEMGMT_FILE_NAME __FILE_NAME__ +#else +#define FILEMGMT_FILE_NAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) +#endif + +#ifndef HYPERAIO_LOG_DOMAIN +#define HYPERAIO_LOG_DOMAIN 0xD004388 +#endif + +#undef HYPERAIO_LOG_TAG +#define HYPERAIO_LOG_TAG "hyperaio" + +#ifdef HILOGD +#undef HILOGD +#endif + +#ifdef HILOGF +#undef HILOGF +#endif + +#ifdef HILOGE +#undef HILOGE +#endif + +#ifdef HILOGW +#undef HILOGW +#endif + +#ifdef HILOGI +#undef HILOGI +#endif + +#define HILOGF(fmt, ...) \ + ((void)HILOG_IMPL(LOG_CORE, LOG_FATAL, HYPERAIO_LOG_DOMAIN, HYPERAIO_LOG_TAG, \ + "[%{public}s:%{public}d->%{public}s] " fmt, FILEMGMT_FILE_NAME, __LINE__, __FUNCTION__, ##__VA_ARGS__)) +#define HILOGE(fmt, ...) \ + ((void)HILOG_IMPL(LOG_CORE, LOG_ERROR, HYPERAIO_LOG_DOMAIN, HYPERAIO_LOG_TAG, \ + "[%{public}s:%{public}d->%{public}s] " fmt, FILEMGMT_FILE_NAME, __LINE__, __FUNCTION__, ##__VA_ARGS__)) +#define HILOGW(fmt, ...) \ + ((void)HILOG_IMPL(LOG_CORE, LOG_WARN, HYPERAIO_LOG_DOMAIN, HYPERAIO_LOG_TAG, \ + "[%{public}s:%{public}d->%{public}s] " fmt, FILEMGMT_FILE_NAME, __LINE__, __FUNCTION__, ##__VA_ARGS__)) +#define HILOGI(fmt, ...) \ + ((void)HILOG_IMPL(LOG_CORE, LOG_INFO, HYPERAIO_LOG_DOMAIN, HYPERAIO_LOG_TAG, \ + "[%{public}s:%{public}d->%{public}s] " fmt, FILEMGMT_FILE_NAME, __LINE__, __FUNCTION__, ##__VA_ARGS__)) +#define HILOGD(fmt, ...) \ + ((void)HILOG_IMPL(LOG_CORE, LOG_DEBUG, HYPERAIO_LOG_DOMAIN, HYPERAIO_LOG_TAG, \ + "[%{public}s:%{public}d->%{public}s] " fmt, FILEMGMT_FILE_NAME, __LINE__, __FUNCTION__, ##__VA_ARGS__)) +} // namespace HyperAio +} // namespace OHOS + +#endif // HYPERAIO_LIBHILOG_H \ No newline at end of file diff --git a/interfaces/kits/hyperaio/src/hyperaio.cpp b/interfaces/kits/hyperaio/src/hyperaio.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c15a62c0478a67a404d710e01c12fcc8579a6375 --- /dev/null +++ b/interfaces/kits/hyperaio/src/hyperaio.cpp @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hyperaio.h" + +#include +#include +#include "accesstoken_kit.h" +#include "hyperaio_trace.h" +#include "libhilog.h" +#include "ipc_skeleton.h" + +namespace OHOS { +namespace HyperAio { +#ifdef HYPERAIO_USE_LIBURING +const uint32_t URING_QUEUE_SIZE = 512; +const uint32_t DELAY = 20; +const uint32_t BATCH_SIZE = 128; +const uint32_t RETRIES = 3; + +static bool HasAccessIouringPermission() +{ + Security::AccessToken::AccessTokenID tokenCaller = IPCSkeleton::GetCallingTokenID(); + const std::string permissionName = "ohos.permission.ALLOW_IOURING"; + int32_t res = Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenCaller, permissionName); + if (res != Security::AccessToken::PermissionState::PERMISSION_GRANTED) { + HILOGE("have no ALLOW_IOURING permission"); + return false; + } + return true; +} + +uint32_t HyperAio::SupportIouring() +{ + HyperaioTrace trace("SupportIouring"); + uint32_t flags = 0; + if (HasAccessIouringPermission()) { + flags |= HYPERAIO_APP_PERMISSION; + } + return flags; +} + +int32_t HyperAio::CtxInit(ProcessIoResultCallBack *callBack) +{ + HyperaioTrace trace("CtxInit"); + if (callBack == nullptr) { + HILOGE("callBack is null"); + return -EINVAL; + } + int32_t ret = io_uring_queue_init(URING_QUEUE_SIZE, &uring_, 0); + if (ret < 0) { + HILOGE("init io_uring failed, ret = %{public}d", ret); + return ret; + } + ioResultCallBack_ = *callBack; + stopThread_.store(false); + harvestThread_ = std::thread(&HyperAio::HarvestRes, this); + initialized_.store(true); + HILOGI("init hyperaio success"); + return EOK; +} + +struct io_uring_sqe* HyperAio::GetSqeWithRetry(struct io_uring *ring) +{ + struct io_uring_sqe *sqe; + for (uint32_t i = 0; i < RETRIES; i++) { + sqe = io_uring_get_sqe(ring); + if (sqe != nullptr) { + return sqe; + } + io_uring_submit(ring); + std::this_thread::sleep_for(std::chrono::milliseconds(DELAY)); + } + return nullptr; +} + +int32_t HyperAio::StartOpenReqs(OpenReqs *req) +{ + HyperaioTrace trace("StartOpenReqs" + std::to_string(req->reqNum)); + if (req == nullptr || req->reqs == nullptr) { + return -EINVAL; + } + if (!initialized_.load()) { + HILOGE("HyperAio is not initialized"); + return -EPERM; + } + uint32_t totalReqs = req->reqNum; + uint32_t count = 0; + for (uint32_t i = 0; i < totalReqs; i++) { + struct io_uring_sqe *sqe = GetSqeWithRetry(&uring_); + if (sqe == nullptr) { + HILOGE("get sqe failed"); + return -ENOMEM; + } + struct OpenInfo *openInfo = &req->reqs[i]; + io_uring_sqe_set_data(sqe, reinterpret_cast(openInfo->userData)); + io_uring_prep_openat(sqe, openInfo->dfd, static_cast(openInfo->path), + openInfo->flags, openInfo->mode); + count++; + if (count >= BATCH_SIZE) { + count = 0; + int32_t ret = io_uring_submit(&uring_); + if (ret < 0) { + HILOGE("submit open reqs failed, ret = %{public}d", ret); + return ret; + } + } + } + if (count > 0 && count < BATCH_SIZE) { + int32_t ret = io_uring_submit(&uring_); + if (ret < 0) { + HILOGE("submit open reqs failed, ret = %{public}d", ret); + return ret; + } + } + return EOK; +} + +int32_t HyperAio::StartReadReqs(ReadReqs *req) +{ + HyperaioTrace trace("StartReadReqs" + std::to_string(req->reqNum)); + if (req == nullptr || req->reqs == nullptr) { + return -EINVAL; + } + if (!initialized_.load()) { + HILOGE("HyperAio is not initialized"); + return -EPERM; + } + uint32_t totalReqs = req->reqNum; + uint32_t count = 0; + for (uint32_t i = 0; i < totalReqs; i++) { + struct io_uring_sqe *sqe = GetSqeWithRetry(&uring_); + if (sqe == nullptr) { + HILOGE("get sqe failed"); + return -ENOMEM; + } + struct ReadInfo *readInfo = &req->reqs[i]; + io_uring_sqe_set_data(sqe, reinterpret_cast(readInfo->userData)); + io_uring_prep_read(sqe, readInfo->fd, readInfo->buf, readInfo->len, readInfo->offset); + count++; + if (count >= BATCH_SIZE) { + count = 0; + int32_t ret = io_uring_submit(&uring_); + if (ret < 0) { + HILOGE("submit read reqs failed, ret = %{public}d", ret); + return ret; + } + } + } + if (count > 0 && count < BATCH_SIZE) { + int32_t ret = io_uring_submit(&uring_); + if (ret < 0) { + HILOGE("submit read reqs failed, ret = %{public}d", ret); + return ret; + } + } + return EOK; +} + +int32_t HyperAio::StartCancelReqs(CancelReqs *req) +{ + HyperaioTrace trace("StartCancelReqs" + std::to_string(req->reqNum)); + if (req == nullptr || req->reqs == nullptr) { + return -EINVAL; + } + if (!initialized_.load()) { + HILOGE("HyperAio is not initialized"); + return -EPERM; + } + uint32_t totalReqs = req->reqNum; + uint32_t count = 0; + for (uint32_t i = 0; i < totalReqs; i++) { + struct io_uring_sqe *sqe = GetSqeWithRetry(&uring_); + if (sqe == nullptr) { + HILOGE("get sqe failed"); + return -ENOMEM; + } + struct CancelInfo *cancelInfo = &req->reqs[i]; + io_uring_sqe_set_data(sqe, reinterpret_cast(cancelInfo->userData)); + io_uring_prep_cancel(sqe, reinterpret_cast(cancelInfo->targetUserData), 0); + count++; + if (count >= BATCH_SIZE) { + count = 0; + int32_t ret = io_uring_submit(&uring_); + if (ret < 0) { + HILOGE("submit cancel reqs failed, ret = %{public}d", ret); + return ret; + } + } + } + if (count > 0 && count < BATCH_SIZE) { + int32_t ret = io_uring_submit(&uring_); + if (ret < 0) { + HILOGE("submit cancel reqs failed, ret = %{public}d", ret); + return ret; + } + } + return EOK; +} + +void HyperAio::HarvestRes() +{ + while (!stopThread_.load()) { + struct io_uring_cqe *cqe; + int32_t ret = io_uring_wait_cqe(&uring_, &cqe); + if (ret < 0 || cqe == nullptr) { + HILOGI("wait cqe failed, ret = %{public}d", ret); + continue; + } + auto response = std::make_unique(cqe->user_data, cqe->res, cqe->flags); + io_uring_cqe_seen(&uring_, cqe); + if (ioResultCallBack_) { + ioResultCallBack_(std::move(response)); + } + } +} + +int32_t HyperAio::DestroyCtx() +{ + stopThread_.store(true); + if (harvestThread_.joinable()) { + harvestThread_.join(); + } + io_uring_queue_exit(&uring_); + initialized_.store(false); + return EOK; +} +#else + +uint32_t HyperAio::SupportIouring() +{ + return 0; +} +int32_t HyperAio::CtxInit(ProcessIoResultCallBack *callBack) +{ + return EINVAL; +} +int32_t HyperAio::StartReadReqs(ReadReqs *req) +{ + return EINVAL; +} +int32_t HyperAio::StartOpenReqs(OpenReqs *req) +{ + return EINVAL; +} +int32_t HyperAio::StartCancelReqs(CancelReqs *req) +{ + return EINVAL; +} +int32_t HyperAio::DestroyCtx() +{ + return EINVAL; +} +#endif +} +} \ No newline at end of file diff --git a/interfaces/kits/hyperaio/src/hyperaio_trace.cpp b/interfaces/kits/hyperaio/src/hyperaio_trace.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b51c24b3404de8448460271adc7ad748ea05e9f3 --- /dev/null +++ b/interfaces/kits/hyperaio/src/hyperaio_trace.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hyperaio_trace.h" + +namespace OHOS { +namespace HyperAio { + +HyperaioTrace::HyperaioTrace(const std::string& value, bool isShowLog) : value_(value) +{ + if (isShowLog) { + HILOGI("%{public}s", value_.c_str()); + } + StartTrace(HITRACE_TAG_OHOS, "[HyperAio]" + value); +} + +void HyperaioTrace::End() +{ + if (!isFinished_) { + FinishTrace(HITRACE_TAG_OHOS); + isFinished_ = true; + } +} + +HyperaioTrace::~HyperaioTrace() +{ + End(); +} +} // namespace HyperAio +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/test/unittest/BUILD.gn b/interfaces/test/unittest/BUILD.gn index 95f924b844e04552b66b00271d787063419395ea..facee8dcebb96279b73358ef82e61369a45d6cd1 100644 --- a/interfaces/test/unittest/BUILD.gn +++ b/interfaces/test/unittest/BUILD.gn @@ -19,4 +19,7 @@ group("unittest") { "remote_uri:remote_uri_test", "task_signal:task_signal_test", ] + if (file_api_feature_inner_hyperaio) { + deps += [ "hyperaio:hyperaio_test" ] + } } diff --git a/interfaces/test/unittest/hyperaio/BUILD.gn b/interfaces/test/unittest/hyperaio/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..fafad4b9031269c8e70da3e8e1e0eae192c75620 --- /dev/null +++ b/interfaces/test/unittest/hyperaio/BUILD.gn @@ -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("//build/test.gni") +import("//foundation/filemanagement/file_api/file_api.gni") + +ohos_unittest("hyperaio_test") { + module_out_path = "file_api/file_api" + + resource_config_file = "../resource/ohos_test.xml" + + sources = [ "hyperaio_test.cpp" ] + + include_dirs = [ + "include", + "${file_api_path}/interfaces/kits/hyperaio/include", + ] + + deps = [ + "${file_api_path}/interfaces/kits/hyperaio:HyperAio", + ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "c_utils:utils", + "c_utils:utilsbase", + "ipc:ipc_core", + "googletest:gtest_main", + ] + if (file_api_feature_inner_hyperaio) { + deps += [ "liburing:liburing" ] + } +} diff --git a/interfaces/test/unittest/hyperaio/hyperaio_test.cpp b/interfaces/test/unittest/hyperaio/hyperaio_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fd3cb8f8c67508fab65f095d99ca09c3385ccbe1 --- /dev/null +++ b/interfaces/test/unittest/hyperaio/hyperaio_test.cpp @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES 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 "hyperaio.h" + +namespace { + using namespace std; + using namespace OHOS::HyperAio; + class HyperAioTest : public testing::Test { + public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase() {}; + void SetUp() {}; + void TearDown() {}; + }; +#ifdef HYPERAIO_USE_LIBURING + const uint64_t userData = 12345; + const uint32_t len = 1024; + std::function)> callBack = [](std::unique_ptr response) { + GTEST_LOG_(INFO) << "HyperAioTest callBack"; + }; + + /** + * @tc.name: HyperAio_StartOpenReqs_0000 + * @tc.desc: Test function of StartOpenReqs() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: AR000HG8M4 + */ + HWTEST_F(HyperAioTest, HyperAio_StartOpenReqs_0000, testing::ext::TestSize.Level1) + { + GTEST_LOG_(INFO) << "HyperAioTest-begin HyperAio_StartOpenReqs_0000"; + std::unique_ptr hyperAio_ = std::make_unique(); + int32_t result = hyperAio_->SupportIouring(); + EXPECT_EQ((result & HYPERAIO_APP_PERMISSION) == 0, true); + if ((result & HYPERAIO_APP_PERMISSION) == 0) { + return; + } + result = hyperAio_->CtxInit(nullptr); + EXPECT_EQ(result, -EINVAL); + GTEST_LOG_(INFO) << "HyperAioTest-end HyperAio_StartOpenReqs_0000"; + } + + /** + * @tc.name: HyperAio_StartOpenReqs_0001 + * @tc.desc: Test function of StartOpenReqs() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: AR000HG8M4 + */ + HWTEST_F(HyperAioTest, HyperAio_StartOpenReqs_0001, testing::ext::TestSize.Level1) + { + GTEST_LOG_(INFO) << "HyperAioTest-begin HyperAio_StartOpenReqs_0001"; + std::unique_ptr hyperAio_ = std::make_unique(); + int32_t result = hyperAio_->SupportIouring(); + EXPECT_EQ((result & HYPERAIO_APP_PERMISSION) == 0, true); + if ((result & HYPERAIO_APP_PERMISSION) == 0) { + return; + } + result = hyperAio_->CtxInit(&callBack); + EXPECT_EQ(result, 0); + OpenInfo openInfo = {0, O_RDWR, 0, nullptr, userData}; + OpenReqs openReqs = {1, &openInfo}; + result = hyperAio_->StartOpenReqs(&openReqs); + EXPECT_EQ(result, 0); + result = hyperAio_->DestroyCtx(); + EXPECT_EQ(result, 0); + GTEST_LOG_(INFO) << "HyperAioTest-end HyperAio_StartOpenReqs_0001"; + } + + /** + * @tc.name: HyperAio_StartOpenReqs_0002 + * @tc.desc: Test function of StartOpenReqs() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: AR000HG8M4 + */ + HWTEST_F(HyperAioTest, HyperAio_StartOpenReqs_0002, testing::ext::TestSize.Level1) + { + GTEST_LOG_(INFO) << "HyperAioTest-begin HyperAio_StartOpenReqs_0002"; + std::unique_ptr hyperAio_ = std::make_unique(); + int32_t result = hyperAio_->SupportIouring(); + EXPECT_EQ((result & HYPERAIO_APP_PERMISSION) == 0, true); + if ((result & HYPERAIO_APP_PERMISSION) == 0) { + return; + } + OpenInfo openInfo = {0, O_RDWR, 0, nullptr, userData}; + OpenReqs openReqs = {1, &openInfo}; + result = hyperAio_->StartOpenReqs(&openReqs); + EXPECT_EQ(result, -EPERM); + GTEST_LOG_(INFO) << "HyperAioTest-end HyperAio_StartOpenReqs_0002"; + } + + /** + * @tc.name: HyperAio_StartReadReqs_0000 + * @tc.desc: Test function of StartReadReqs() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: AR000HG8M4 + */ + HWTEST_F(HyperAioTest, HyperAio_StartReadReqs_0000, testing::ext::TestSize.Level1) + { + GTEST_LOG_(INFO) << "HyperAioTest-begin HyperAio_StartReadReqs_0000"; + std::unique_ptr hyperAio_ = std::make_unique(); + int32_t result = hyperAio_->SupportIouring(); + EXPECT_EQ((result & HYPERAIO_APP_PERMISSION) == 0, true); + if ((result & HYPERAIO_APP_PERMISSION) == 0) { + return; + } + result = hyperAio_->CtxInit(nullptr); + EXPECT_EQ(result, -EINVAL); + GTEST_LOG_(INFO) << "HyperAioTest-end HyperAio_StartReadReqs_0000"; + } + + /** + * @tc.name: HyperAio_StartReadReqs_0001 + * @tc.desc: Test function of StartReadReqs() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: AR000HG8M4 + */ + HWTEST_F(HyperAioTest, HyperAio_StartReadReqs_0001, testing::ext::TestSize.Level1) + { + GTEST_LOG_(INFO) << "HyperAioTest-begin HyperAio_StartReadReqs_0001"; + std::unique_ptr hyperAio_ = std::make_unique(); + int32_t result = hyperAio_->SupportIouring(); + EXPECT_EQ((result & HYPERAIO_APP_PERMISSION) == 0, true); + if ((result & HYPERAIO_APP_PERMISSION) == 0) { + return; + } + result = hyperAio_->CtxInit(&callBack); + EXPECT_EQ(result, 0); + ReadInfo readInfo = {0, len, 0, nullptr, userData}; + ReadReqs readReqs = {1, &readInfo}; + result = hyperAio_->StartReadReqs(&readReqs); + EXPECT_EQ(result, 0); + result = hyperAio_->DestroyCtx(); + EXPECT_EQ(result, 0); + GTEST_LOG_(INFO) << "HyperAioTest-end HyperAio_StartReadReqs_0001"; + } + + /** + * @tc.name: HyperAio_StartReadReqs_0002 + * @tc.desc: Test function of StartReadReqs() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: AR000HG8M4 + */ + HWTEST_F(HyperAioTest, HyperAio_StartReadReqs_0002, testing::ext::TestSize.Level1) + { + GTEST_LOG_(INFO) << "HyperAioTest-begin HyperAio_StartReadReqs_0002"; + std::unique_ptr hyperAio_ = std::make_unique(); + int32_t result = hyperAio_->SupportIouring(); + EXPECT_EQ((result & HYPERAIO_APP_PERMISSION) == 0, true); + if ((result & HYPERAIO_APP_PERMISSION) == 0) { + return; + } + ReadInfo readInfo = {0, len, 0, nullptr, userData}; + ReadReqs readReqs = {1, &readInfo}; + result = hyperAio_->StartReadReqs(&readReqs); + EXPECT_EQ(result, -EPERM); + GTEST_LOG_(INFO) << "HyperAioTest-end HyperAio_StartReadReqs_0002"; + } + + /** + * @tc.name: HyperAio_StartCancelReqs_0000 + * @tc.desc: Test function of StartCancelReqs() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: AR000HG8M4 + */ + HWTEST_F(HyperAioTest, HyperAio_StartCancelReqs_0000, testing::ext::TestSize.Level1) + { + GTEST_LOG_(INFO) << "HyperAioTest-begin HyperAio_StartCancelReqs_0000"; + std::unique_ptr hyperAio_ = std::make_unique(); + int32_t result = hyperAio_->SupportIouring(); + EXPECT_EQ((result & HYPERAIO_APP_PERMISSION) == 0, true); + if ((result & HYPERAIO_APP_PERMISSION) == 0) { + return; + } + result = hyperAio_->CtxInit(nullptr); + EXPECT_EQ(result, -EINVAL); + GTEST_LOG_(INFO) << "HyperAioTest-end HyperAio_StartCancelReqs_0000"; + } + + /** + * @tc.name: HyperAio_StartCancelReqs_0001 + * @tc.desc: Test function of StartCancelReqs() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: AR000HG8M4 + */ + HWTEST_F(HyperAioTest, HyperAio_StartCancelReqs_0001, testing::ext::TestSize.Level1) + { + GTEST_LOG_(INFO) << "HyperAioTest-begin HyperAio_StartCancelReqs_0001"; + std::unique_ptr hyperAio_ = std::make_unique(); + int32_t result = hyperAio_->SupportIouring(); + EXPECT_EQ((result & HYPERAIO_APP_PERMISSION) == 0, true); + if ((result & HYPERAIO_APP_PERMISSION) == 0) { + return; + } + result = hyperAio_->CtxInit(&callBack); + EXPECT_EQ(result, 0); + CancelInfo cancelInfo = {userData, 0}; + CancelReqs cancelReqs = {1, &cancelInfo}; + result = hyperAio_->StartCancelReqs(&cancelReqs); + EXPECT_EQ(result, 0); + result = hyperAio_->DestroyCtx(); + EXPECT_EQ(result, 0); + GTEST_LOG_(INFO) << "HyperAioTest-end HyperAio_StartCancelReqs_0001"; + } + + /** + * @tc.name: HyperAio_StartCancelReqs_0002 + * @tc.desc: Test function of StartCancelReqs() interface for SUCCESS. + * @tc.size: MEDIUM + * @tc.type: FUNC + * @tc.level Level 1 + * @tc.require: AR000HG8M4 + */ + HWTEST_F(HyperAioTest, HyperAio_StartCancelReqs_0002, testing::ext::TestSize.Level1) + { + GTEST_LOG_(INFO) << "HyperAioTest-begin HyperAio_StartCancelReqs_0002"; + std::unique_ptr hyperAio_ = std::make_unique(); + int32_t result = hyperAio_->SupportIouring(); + EXPECT_EQ((result & HYPERAIO_APP_PERMISSION) == 0, true); + if ((result & HYPERAIO_APP_PERMISSION) == 0) { + return; + } + CancelInfo cancelInfo = {userData, 0}; + CancelReqs cancelReqs = {1, &cancelInfo}; + result = hyperAio_->StartCancelReqs(&cancelReqs); + EXPECT_EQ(result, -EPERM); + GTEST_LOG_(INFO) << "HyperAioTest-end HyperAio_StartCancelReqs_0002"; + } +#endif +}