diff --git a/docs/guides/plugins.md b/docs/guides/plugins.md index 7afc46cf7..e6b8d8bd2 100644 --- a/docs/guides/plugins.md +++ b/docs/guides/plugins.md @@ -215,3 +215,5 @@ Kernel also uses typed construction while retaining its public `*_impl` and `ker Consul follows the same construction pattern while retaining all three public headers and types. Its private factory is not installed; the module keeps its interface RTTI key and disabled updates. Rebuild Consul and consumers together because its public implementation/plugin layouts change. See [Consul construction migration](../reference/directory-structure.md#typed-consul-construction) for test entry points and dependency conditions. Etcd Client also retains all five public headers and types while using typed bases, a private interface-returning factory and explicit entry/exit functions. Its interface RTTI key and disabled updates are unchanged. Rebuild the plugin and consumers together because the public implementation/plugin layouts change. The [Etcd Client construction migration](../reference/directory-structure.md#typed-etcd-client-construction) describes optional JSON dependencies and tests without an Etcd service. + +OSS SDK uses the same typed bases and private interface-returning factory while retaining all three public headers/types, its interface RTTI key and disabled updates. Rebuild the plugin and consumers together for the public layout change. Typed unregistration replaces its undefined legacy deregistration call; the implementation remains a TODO scaffold. See [OSS SDK construction migration](../reference/directory-structure.md#typed-oss-sdk-construction) for build and test boundaries. diff --git a/docs/guides/plugins_CN.md b/docs/guides/plugins_CN.md index ef5d6defb..9f9a2126b 100644 --- a/docs/guides/plugins_CN.md +++ b/docs/guides/plugins_CN.md @@ -202,3 +202,5 @@ Kernel 同样使用类型化构造,并保留公开 `*_impl`、`kernel_plugin` Consul 使用相同构造方式,保留全部三个公开头与类型。私有工厂不安装;模块保留接口 RTTI 键和禁用 update 的选择。公开实现/插件布局发生变化,Consul 与消费者必须一起重建。测试入口与依赖条件见 [Consul 构造迁移](../reference/directory-structure_CN.md#consul-类型化构造)。 Etcd Client 使用类型化基类、返回接口的私有工厂与显式入口/出口,保留全部五个公开头与类型。接口 RTTI 键和禁用 update 的选择不变。公开实现/插件布局发生变化,插件与消费者必须一起重建。可选 JSON 依赖与无需 Etcd 服务的测试见 [Etcd Client 构造迁移](../reference/directory-structure_CN.md#etcd-client-类型化构造)。 + +OSS SDK 使用相同的类型化基类和返回接口的私有工厂,保留全部三个公开头/类型、接口 RTTI 键和禁用 update 的选择。公开布局发生变化,插件与消费者必须一起重建。类型化注销替代未定义的旧注销调用;实现仍为 TODO 骨架。构建与测试边界见 [OSS SDK 构造迁移](../reference/directory-structure_CN.md#oss-sdk-类型化构造)。 diff --git a/docs/project-layout.md b/docs/project-layout.md index 6ce9b31b3..b17dafa02 100644 --- a/docs/project-layout.md +++ b/docs/project-layout.md @@ -133,4 +133,6 @@ cmake -S tests/consumer/etcd_client -B etcd-client-headers -G Ninja \ cmake --build etcd-client-headers --target check-etcd-client-headers --parallel 2 ``` +OSS SDK retains its three public headers and types through typed construction; rebuild the plugin and consumers together because public class layouts change. See [OSS SDK construction migration](reference/directory-structure.md#typed-oss-sdk-construction) for optional build conditions and construction/export checks. The implementation remains a TODO scaffold. + Header mapping does not establish Consul, Kafka or OSS SDK runtime compatibility. Physic and `physics_scene` still require the unsupported legacy PhysX 3 integration and retain their explicit configuration failure; no passing PhysX build is claimed. diff --git a/docs/project-layout_CN.md b/docs/project-layout_CN.md index 82a8ee230..00faadbad 100644 --- a/docs/project-layout_CN.md +++ b/docs/project-layout_CN.md @@ -123,4 +123,6 @@ cmake -S tests/consumer/etcd_client -B etcd-client-headers -G Ninja \ cmake --build etcd-client-headers --target check-etcd-client-headers --parallel 2 ``` +OSS SDK 使用类型化构造,保留全部三个公开头和类型;公开类布局发生变化,插件与消费者必须一起重建。可选构建条件及构造/导出检查见 [OSS SDK 构造迁移](reference/directory-structure_CN.md#oss-sdk-类型化构造)。实现仍为 TODO 骨架。 + 头文件映射检查不代表 Consul、Kafka、OSS SDK 的运行时兼容性已经验证。Physic 与 `physics_scene` 仍依赖未受支持的旧版 PhysX 3 集成,保留明确的配置失败;此处没有宣称 PhysX 构建通过。 diff --git a/docs/reference/build-options.md b/docs/reference/build-options.md index 1825ad741..465a54877 100644 --- a/docs/reference/build-options.md +++ b/docs/reference/build-options.md @@ -39,10 +39,12 @@ cmake -S . -B build -DARK_BUILD_APPLICATIONS=ON \ cmake --build build --target ark_mysql_plugin ark_redis_plugin ``` -All official plugin public headers are copied from explicit lists at configuration time into each build tree's generated plugin header mapping. Each `ark::` API target carries that include root even with runtime plugins disabled. MySQL, Redis, Utility, Net, Bus and HTTP exclude private assembly and factories. Kernel retains all 38 existing headers, including `kernel_plugin.hpp`; Consul, Etcd Client, Kafka, OSS SDK and Physic retain all 22 existing public headers, including implementation and assembly headers. Registration keys, public type visibility and optional plugin policies are retained; [Kernel typed construction](kernel.md#typed-kernel-construction), [Consul typed construction](directory-structure.md#typed-consul-construction) and [Etcd Client typed construction](directory-structure.md#typed-etcd-client-construction) change public class layouts and require rebuilding consumers. Their private factory headers are excluded from mapping and installation; header mapping does not validate optional driver integrations. Each public header has one co-located source; its generated include mapping belongs to the selected build tree, rather than a second source layout. +All official plugin public headers are copied from explicit lists at configuration time into each build tree's generated plugin header mapping. Each `ark::` API target carries that include root even with runtime plugins disabled. MySQL, Redis, Utility, Net, Bus and HTTP exclude private assembly and factories. Kernel retains all 38 existing headers, including `kernel_plugin.hpp`; Consul, Etcd Client, Kafka, OSS SDK and Physic retain all 22 existing public headers, including implementation and assembly headers. Registration keys, public type visibility and optional plugin policies are retained; [Kernel typed construction](kernel.md#typed-kernel-construction), [Consul typed construction](directory-structure.md#typed-consul-construction), [Etcd Client typed construction](directory-structure.md#typed-etcd-client-construction) and [OSS SDK typed construction](directory-structure.md#typed-oss-sdk-construction) change public class layouts and require rebuilding consumers. Their private factory headers are excluded from mapping and installation; header mapping does not validate optional driver integrations. Each public header has one co-located source; its generated include mapping belongs to the selected build tree, rather than a second source layout. Applications CI explicitly enables Consul and Etcd Client on Linux, macOS and Windows. Its `check-core` run includes their construction, DLL lifecycle and production export checks; these checks require no Consul or Etcd service and do not establish service interoperability. Etcd Client keeps its existing default `ON` selection and can be disabled with `ARK_BUILD_PLUGIN_ETCD_CLIENT=OFF`. Building it requires the existing `nlohmann_json` package (`etcd-client` vcpkg feature); disabling it does not add that JSON dependency to core tests. +OSS SDK remains optional and off by default (`ARK_BUILD_PLUGIN_OSSSDK=OFF`). Core tests include its real factory/assembly and controlled DSO checks without Protobuf or a runtime plugin. With the runtime plugin selected, `check-oss-sdk-plugin` also loads the actual DSO and checks its exports; `check-core` includes the applicable checks. The implementation is still a TODO scaffold, with no object-storage client or service acceptance. See [OSS SDK construction migration](directory-structure.md#typed-oss-sdk-construction). + Link a consumer to `ark::mysql` and/or `ark::redis` for the public headers and usage requirements. These public interface targets do not load a runtime library. Deploy the selected libraries with the launcher and add their stems to the application's manifest: ```toml diff --git a/docs/reference/build-options_CN.md b/docs/reference/build-options_CN.md index d9d1cd082..2eec5a7a1 100644 --- a/docs/reference/build-options_CN.md +++ b/docs/reference/build-options_CN.md @@ -39,10 +39,12 @@ cmake -S . -B build -DARK_BUILD_APPLICATIONS=ON \ cmake --build build --target ark_mysql_plugin ark_redis_plugin ``` -全部官方插件的公开头通过显式清单在配置阶段复制到各构建树生成的插件公开头映射。各 `ark::` API target 传递该目录,插件关闭时仍可使用。MySQL、Redis、Utility、Net、Bus、HTTP 的私有装配头和工厂不进入映射;Kernel 保留包括 `kernel_plugin.hpp` 在内的原有 38 个头;Consul、Etcd Client、Kafka、OSS SDK、Physic 保留包括实现头与装配头在内的原有 22 个公开头。注册键、公开类型可见性和可选插件策略继续保留;[Kernel 类型化构造](kernel_CN.md#kernel-类型化构造)、[Consul 类型化构造](directory-structure_CN.md#consul-类型化构造)与 [Etcd Client 类型化构造](directory-structure_CN.md#etcd-client-类型化构造)改变公开类布局,需要重建消费者。这些私有工厂头均不映射、不安装;头文件映射不代表可选驱动集成已经验证。每个公共头仅有一份共置源码;生成的头文件映射属于选定构建树,不构成第二棵源码目录。 +全部官方插件的公开头通过显式清单在配置阶段复制到各构建树生成的插件公开头映射。各 `ark::` API target 传递该目录,插件关闭时仍可使用。MySQL、Redis、Utility、Net、Bus、HTTP 的私有装配头和工厂不进入映射;Kernel 保留包括 `kernel_plugin.hpp` 在内的原有 38 个头;Consul、Etcd Client、Kafka、OSS SDK、Physic 保留包括实现头与装配头在内的原有 22 个公开头。注册键、公开类型可见性和可选插件策略继续保留;[Kernel 类型化构造](kernel_CN.md#kernel-类型化构造)、[Consul 类型化构造](directory-structure_CN.md#consul-类型化构造)、[Etcd Client 类型化构造](directory-structure_CN.md#etcd-client-类型化构造)与 [OSS SDK 类型化构造](directory-structure_CN.md#oss-sdk-类型化构造)改变公开类布局,需要重建消费者。这些私有工厂头均不映射、不安装;头文件映射不代表可选驱动集成已经验证。每个公共头仅有一份共置源码;生成的头文件映射属于选定构建树,不构成第二棵源码目录。 应用 CI 在 Linux、macOS、Windows 显式启用 Consul 与 Etcd Client,`check-core` 包含两者的构造、动态库生命周期与生产库导出检查。这些检查不需要 Consul 或 Etcd 服务,也不代表服务互通验收。Etcd Client 保留现有默认 `ON` 选择,可通过 `ARK_BUILD_PLUGIN_ETCD_CLIENT=OFF` 关闭。构建它需要现有 `nlohmann_json` 软件包(vcpkg 的 `etcd-client` feature);关闭它不会向核心测试增加该 JSON 依赖。 +OSS SDK 保持可选且默认关闭(`ARK_BUILD_PLUGIN_OSSSDK=OFF`)。核心测试包含真实工厂/装配与受控 DSO 检查,无需 Protobuf 或运行时插件。选中运行时插件后,`check-oss-sdk-plugin` 还加载真实 DSO 并检查导出;`check-core` 包含当前条件下可用的检查。实现仍为 TODO 骨架,没有对象存储客户端或服务验收。参见 [OSS SDK 构造迁移](directory-structure_CN.md#oss-sdk-类型化构造)。 + 业务插件链接 `ark::mysql` 和/或 `ark::redis`,以获取公开头文件和编译要求;公共接口目标不会加载运行时动态库。将所需动态库与启动器一起部署,并在应用清单中填写库名称: ```toml diff --git a/docs/reference/directory-structure.md b/docs/reference/directory-structure.md index 56ac10a5c..bf3360351 100644 --- a/docs/reference/directory-structure.md +++ b/docs/reference/directory-structure.md @@ -152,6 +152,8 @@ cmake -S tests/consumer/etcd_client -B etcd-client-headers -G Ninja \ cmake --build etcd-client-headers --target check-etcd-client-headers --parallel 2 ``` +OSS SDK retains its three public headers and types through typed construction; rebuild the plugin and consumers together because public class layouts change. See [OSS SDK construction migration](directory-structure.md#typed-oss-sdk-construction) for optional build conditions and construction/export checks. The implementation remains a TODO scaffold. + Header mapping does not establish Consul, Kafka or OSS SDK runtime compatibility. Physic and `physics_scene` still require the unsupported legacy PhysX 3 integration and retain their explicit configuration failure; no passing PhysX build is claimed. @@ -196,3 +198,23 @@ cmake --build build --target check-etcd-client-plugin --parallel 1 This target includes `check-etcd-client-construction`: actual factory/assembly doctest cases, plus a controlled-factory DSO using the production entry/exit source to check configuration handoff, interface metadata, disabled updates, exactly-once ownership and repeated stop. A separate process loads the actual production plugin, checks its entry/exit exports and unloads it. `check-core` includes both checks when the runtime plugin is selected; disabled-plugin core builds do not acquire the JSON dependency. Applications CI explicitly enables the plugin and runs these checks through its existing `check-core` job. These tests do not run an Etcd service or exercise production HTTP/Etcd interoperability. They establish construction and DSO boundaries, not a completed Registry or arbitrary hot-update safety. + +## Typed OSS SDK construction + +**Breaking ABI/layout change:** `oss_sdk_module_impl` now inherits `module_base` and `oss_sdk_plugin` inherits `plugin_base`. Rebuild OSS SDK and consumers together. All three public headers, their `` paths and public types remain available through `ark::osssdk`; the `oss_sdk_module` interface is unchanged. The C++ plugin boundary does not promise compiler-independent ABI compatibility. + +The private `oss_sdk_factory.hpp` returns `std::unique_ptr` and is excluded from public mappings and installation. Explicit `DllEntryPlugin` / `DllExitPlugin` retain platform exports and logger initialization. Installation retains the original `oss_sdk_module` interface RTTI key and disabled updates. Typed unregistration replaces the undefined `ARK_DEREGISTER_MODULE` invocation and destroys the owned module. Configuration storage and the inherited default update method are preserved. The implementation remains a TODO scaffold: no OSS client, request API or object-storage protocol is added. + +With `ARK_BUILD_CORE_TESTS=ON`, `check-oss-sdk-construction` compiles the real factory and assembly into doctest cases and uses the production entry/exit source with a counted controlled factory in a DSO. Checks cover retained public bases/types, factory metadata, interface registration, duplicate rejection, disabled updates, configuration handoff, exactly-once destruction and repeated stop. This target requires only the normal core/arknet dependencies; it needs no runtime plugin, Protobuf, JSON package or object-storage service: + +```sh +cmake --build build --target check-oss-sdk-construction --parallel 1 +``` + +The runtime plugin remains off by default. Enable `ARK_BUILD_APPLICATIONS=ON`, `ARK_BUILD_PLUGIN_OSSSDK=ON`, `ARK_BUILD_PROTO=ON` and `ARK_BUILD_CORE_TESTS=ON` to additionally build the actual `ark_oss_sdk_plugin` DSO and inspect its entry/exit exports in a separate process: + +```sh +cmake --build build --target check-oss-sdk-plugin --parallel 1 +``` + +Application builds retain their existing Protobuf, configuration and Boost.Asio requirements. `check-core` includes the applicable OSS SDK construction/export checks. No external OSS SDK dependency is introduced. These tests establish construction and DSO boundaries only; they do not establish OSS client functionality, service interoperability or arbitrary hot-update safety. diff --git a/docs/reference/directory-structure_CN.md b/docs/reference/directory-structure_CN.md index 25d79a69f..27b49cf93 100644 --- a/docs/reference/directory-structure_CN.md +++ b/docs/reference/directory-structure_CN.md @@ -142,6 +142,8 @@ cmake -S tests/consumer/etcd_client -B etcd-client-headers -G Ninja \ cmake --build etcd-client-headers --target check-etcd-client-headers --parallel 2 ``` +OSS SDK 使用类型化构造,保留全部三个公开头和类型;公开类布局发生变化,插件与消费者必须一起重建。可选构建条件及构造/导出检查见 [OSS SDK 构造迁移](directory-structure_CN.md#oss-sdk-类型化构造)。实现仍为 TODO 骨架。 + 头文件映射检查不代表 Consul、Kafka、OSS SDK 的运行时兼容性已经验证。Physic 与 `physics_scene` 仍依赖未受支持的旧版 PhysX 3 集成,保留明确的配置失败;此处没有宣称 PhysX 构建通过。 ## 安装目录 @@ -186,3 +188,23 @@ cmake --build build --target check-etcd-client-plugin --parallel 1 该目标包含 `check-etcd-client-construction`:真实工厂/装配的 doctest 用例,以及使用生产入口/出口源码与受控工厂的 DSO 测试,覆盖配置传递、接口元数据、禁用 update、所有权恰好销毁一次和重复 stop。另一个独立进程加载真实生产插件,检查入口/出口导出后卸载。选中运行时插件时,`check-core` 包含这两项检查;关闭插件的核心构建不增加 JSON 依赖。应用 CI 显式启用该插件,通过现有 `check-core` 任务执行检查。 这些测试不启动 Etcd 服务,不执行生产 HTTP/Etcd 互通验收,只验证构造与 DSO 边界,不代表 Registry 已完成,也不证明任意热更新安全。 + +## OSS SDK 类型化构造 + +**ABI/布局不兼容变更:** `oss_sdk_module_impl` 现在继承 `module_base`,`oss_sdk_plugin` 继承 `plugin_base`。OSS SDK 与消费者必须一起重建。全部三个公开头、`` 路径和公开类型继续通过 `ark::osssdk` 提供,`oss_sdk_module` 接口不变。C++ 插件边界不承诺跨编译器的 ABI 兼容性。 + +私有 `oss_sdk_factory.hpp` 返回 `std::unique_ptr`,不映射、不安装。显式 `DllEntryPlugin`/`DllExitPlugin` 保留平台导出和日志初始化。安装时沿用 `oss_sdk_module` 接口 RTTI 键,继续禁用 update。类型化注销替代未定义的 `ARK_DEREGISTER_MODULE` 调用,销毁拥有的模块。配置存储和继承的默认 update 方法保持不变。实现仍为 TODO 骨架,不增加 OSS 客户端、请求 API 或对象存储协议。 + +开启 `ARK_BUILD_CORE_TESTS=ON` 后,`check-oss-sdk-construction` 将真实工厂与装配编入 doctest 用例,并使用生产入口/出口源码与带计数的受控工厂构建 DSO。检查覆盖保留的公开基类/类型、工厂元数据、接口注册、重复注册拒绝、禁用 update、配置传递、恰好销毁一次和重复 stop。该目标仅需要通常的 core/arknet 依赖,无需运行时插件、Protobuf、JSON 软件包或对象存储服务: + +```sh +cmake --build build --target check-oss-sdk-construction --parallel 1 +``` + +运行时插件默认保持关闭。开启 `ARK_BUILD_APPLICATIONS=ON`、`ARK_BUILD_PLUGIN_OSSSDK=ON`、`ARK_BUILD_PROTO=ON` 与 `ARK_BUILD_CORE_TESTS=ON` 后,还可构建真实 `ark_oss_sdk_plugin` DSO,并在独立进程中检查入口/出口导出: + +```sh +cmake --build build --target check-oss-sdk-plugin --parallel 1 +``` + +应用构建仍需要现有 Protobuf、配置模块与 Boost.Asio。`check-core` 包含当前条件下可用的 OSS SDK 构造/导出检查,不增加外部 OSS SDK 依赖。这些测试只验证构造与 DSO 边界,不代表 OSS 客户端功能、服务互通或任意热更新安全已经通过验收。 diff --git a/src/plugins/README.md b/src/plugins/README.md index bb41192b6..24ba933db 100755 --- a/src/plugins/README.md +++ b/src/plugins/README.md @@ -28,4 +28,6 @@ Kernel co-locates its 38 existing headers with its cpp files in `src/plugins/ker Consul retains its three public headers and implementation/plugin types while using typed construction, a private owning factory and explicit entry points. Rebuild Consul and consumers together because the public class layouts change. The single interface registration key, disabled updates and request behavior are preserved. See [Consul construction migration](../../docs/reference/directory-structure.md#typed-consul-construction) for build conditions and service-free construction checks. -The other four legacy plugin families retain 19 byte-identical headers. Mapping checks do not validate Consul, Kafka or OSS SDK runtime integrations. Physic retains the unsupported PhysX 3 configuration failure; see [optional legacy dependencies](../../docs/dependencies.md#optional-legacy-integrations). +Kafka and Physic retain their original public headers. Mapping checks do not validate Consul, Kafka or OSS SDK runtime integrations. Physic retains the unsupported PhysX 3 configuration failure; see [optional legacy dependencies](../../docs/dependencies.md#optional-legacy-integrations). + +OSS SDK retains all three public headers and types while using typed construction with a private factory and explicit entry points. Rebuild the plugin and consumers together for the public layout change. It remains off by default and retains its TODO scaffold; construction/export checks add no object-storage client capability. See [OSS SDK construction migration](../../docs/reference/directory-structure.md#typed-oss-sdk-construction). diff --git a/src/plugins/README_CN.md b/src/plugins/README_CN.md index bed2c6eb9..97e8ded49 100644 --- a/src/plugins/README_CN.md +++ b/src/plugins/README_CN.md @@ -28,4 +28,6 @@ Kernel 的原有 38 个头与 cpp 共置于 `src/plugins/kernel/`,通过 `ark: Consul 保留原有三个公开头及实现/插件类型,同时使用类型化构造、私有拥有型工厂和显式入口。公开类布局发生变化,Consul 与消费者必须一起重建。唯一接口注册键、禁用 update 与请求行为保持不变。构建条件及无需服务的构造检查见 [Consul 构造迁移](../../docs/reference/directory-structure_CN.md#consul-类型化构造)。 -其他四类旧插件保留原有 19 个头的全部字节。映射检查不代表 Consul、Kafka、OSS SDK 的运行时集成已经验证。Physic 保留未受支持的 PhysX 3 配置失败;参见[可选旧集成依赖](../../docs/dependencies_CN.md)。 +Kafka 与 Physic 保留原有公开头。映射检查不代表 Consul、Kafka、OSS SDK 的运行时集成已经验证。Physic 保留未受支持的 PhysX 3 配置失败;参见[可选旧集成依赖](../../docs/dependencies_CN.md)。 + +OSS SDK 使用类型化构造、私有工厂与显式入口,保留全部三个公开头和类型。公开布局发生变化,插件与消费者必须一起重建。插件默认保持关闭,实现仍为 TODO 骨架;构造/导出检查不增加对象存储客户端能力。参见 [OSS SDK 构造迁移](../../docs/reference/directory-structure_CN.md#oss-sdk-类型化构造)。 diff --git a/src/plugins/osssdk/oss_sdk_factory.hpp b/src/plugins/osssdk/oss_sdk_factory.hpp new file mode 100644 index 000000000..c4c6fba0a --- /dev/null +++ b/src/plugins/osssdk/oss_sdk_factory.hpp @@ -0,0 +1,13 @@ +// Copyright (c) 2026 OpenArkStudio. Licensed under Apache-2.0. See LICENSE. +#pragma once + +#include + +#include "ark/osssdk/oss_sdk_module.hpp" + +// Plugin-private construction; deliberately absent from public header mappings. +namespace ark::detail { + +std::unique_ptr make_oss_sdk_module(); + +} // namespace ark::detail diff --git a/src/plugins/osssdk/oss_sdk_module_impl.cpp b/src/plugins/osssdk/oss_sdk_module_impl.cpp index 061bfa3a8..c5619a994 100644 --- a/src/plugins/osssdk/oss_sdk_module_impl.cpp +++ b/src/plugins/osssdk/oss_sdk_module_impl.cpp @@ -19,9 +19,12 @@ */ #include "ark/osssdk/oss_sdk_module_impl.hpp" +#include "oss_sdk_factory.hpp" namespace ark { -//method realization +std::unique_ptr detail::make_oss_sdk_module() { + return std::make_unique(); +} } // namespace ark diff --git a/src/plugins/osssdk/oss_sdk_module_impl.hpp b/src/plugins/osssdk/oss_sdk_module_impl.hpp index fad7a70e5..734e3b0d3 100644 --- a/src/plugins/osssdk/oss_sdk_module_impl.hpp +++ b/src/plugins/osssdk/oss_sdk_module_impl.hpp @@ -20,14 +20,13 @@ #pragma once +#include "ark/module_base.hpp" #include "ark/osssdk/oss_sdk_module.hpp" -#include "ark/plugin_manager.hpp" namespace ark { -class oss_sdk_module_impl final : public oss_sdk_module +class oss_sdk_module_impl final : public module_base { - ARK_DECLARE_MODULE_FUNCTIONS public: // TODO diff --git a/src/plugins/osssdk/oss_sdk_plugin.cpp b/src/plugins/osssdk/oss_sdk_plugin.cpp index df8d665b8..d20d4321e 100644 --- a/src/plugins/osssdk/oss_sdk_plugin.cpp +++ b/src/plugins/osssdk/oss_sdk_plugin.cpp @@ -18,21 +18,34 @@ * */ -#include "ark/osssdk/oss_sdk_module_impl.hpp" +#include + #include "ark/osssdk/oss_sdk_plugin.hpp" +#include "oss_sdk_factory.hpp" namespace ark { -ARK_DECLARE_PLUGIN_DLL_FUNCTION(oss_sdk_plugin) +ARK_EXPORT_FUNC void DllEntryPlugin(plugin_manager* manager, const std::string& name, logger* log) { + logger::init(log); + manager->register_plugin(name); +} + +ARK_EXPORT_FUNC void DllExitPlugin(plugin_manager* manager) { + manager->unregister_plugin(); +} void oss_sdk_plugin::install() { - // install module - ARK_REGISTER_MODULE(oss_sdk_module, oss_sdk_module_impl); + if (!register_module(detail::make_oss_sdk_module(), module_update::disabled)) + { + throw std::runtime_error("OSS SDK module registration rejected"); + } } void oss_sdk_plugin::uninstall() { - // uninstall module - ARK_DEREGISTER_MODULE(oss_sdk_module, oss_sdk_module_impl); + if (!unregister_module()) + { + throw std::runtime_error("OSS SDK module unregistration rejected"); + } } } // namespace ark diff --git a/src/plugins/osssdk/oss_sdk_plugin.hpp b/src/plugins/osssdk/oss_sdk_plugin.hpp index 500bf3167..349ad0c5a 100644 --- a/src/plugins/osssdk/oss_sdk_plugin.hpp +++ b/src/plugins/osssdk/oss_sdk_plugin.hpp @@ -20,11 +20,15 @@ #pragma once -#include "ark/plugin.hpp" -#include "ark/plugin_manager.hpp" +#include "ark/plugin_base.hpp" namespace ark { -ARK_DECLARE_PLUGIN(oss_sdk_plugin) +class oss_sdk_plugin final : public plugin_base +{ +public: + void install() override; + void uninstall() override; +}; } // namespace ark \ No newline at end of file diff --git a/tests/core/CMakeLists.txt b/tests/core/CMakeLists.txt index 927446e32..3315fdc4d 100644 --- a/tests/core/CMakeLists.txt +++ b/tests/core/CMakeLists.txt @@ -224,6 +224,8 @@ if(ARK_BUILD_PROTO) add_dependencies(check-core check-kernel-initialization) endif() +add_subdirectory(../osssdk "${CMAKE_CURRENT_BINARY_DIR}/osssdk") + if(ARK_BUILD_PROTO AND ARK_BUILD_CONFIG) add_subdirectory(../consul "${CMAKE_CURRENT_BINARY_DIR}/consul") endif() diff --git a/tests/osssdk/CMakeLists.txt b/tests/osssdk/CMakeLists.txt new file mode 100644 index 000000000..cbf91e03f --- /dev/null +++ b/tests/osssdk/CMakeLists.txt @@ -0,0 +1,36 @@ +# Copyright (c) 2026 OpenArkStudio. Licensed under Apache-2.0. See LICENSE. +set(oss_sdk_source "${PROJECT_SOURCE_DIR}/src/plugins/osssdk") + +# Compile real assembly/factory locally too: private C++ symbols are not DLL exports. +add_executable(ark_oss_sdk_construction_tests ../core/main.cpp construction.cpp + "${oss_sdk_source}/oss_sdk_plugin.cpp" "${oss_sdk_source}/oss_sdk_module_impl.cpp") +set_property(TARGET ark_oss_sdk_construction_tests PROPERTY LINK_LIBRARIES + ark::osssdk) +target_include_directories(ark_oss_sdk_construction_tests PRIVATE "${oss_sdk_source}") + +# A controlled module exercises the actual entry/exit functions without object-storage services. +add_library(ark_oss_sdk_entry_probe SHARED entry_factory.cpp "${oss_sdk_source}/oss_sdk_plugin.cpp") +set_property(TARGET ark_oss_sdk_entry_probe PROPERTY LINK_LIBRARIES ark::osssdk) +target_include_directories(ark_oss_sdk_entry_probe PRIVATE "${oss_sdk_source}") +set_target_properties(ark_oss_sdk_entry_probe PROPERTIES PREFIX "") +add_executable(ark_oss_sdk_entry_tests entry.cpp) +set_property(TARGET ark_oss_sdk_entry_tests PROPERTY LINK_LIBRARIES ark::osssdk) + +add_custom_target(check-oss-sdk-construction + COMMAND $ + COMMAND $ "$/" "ark_oss_sdk_entry_probe" + DEPENDS ark_oss_sdk_construction_tests ark_oss_sdk_entry_tests ark_oss_sdk_entry_probe + USES_TERMINAL VERBATIM) + +if(TARGET ark_oss_sdk_plugin) + # Keep real DSO export inspection separate from the host linking static AFProto. + add_executable(ark_oss_sdk_exports_tests exports.cpp) + set_property(TARGET ark_oss_sdk_exports_tests PROPERTY LINK_LIBRARIES ark::core) + add_custom_target(check-oss-sdk-plugin + COMMAND $ "$/" "ark_oss_sdk_plugin" + DEPENDS ark_oss_sdk_exports_tests ark_oss_sdk_plugin check-oss-sdk-construction + USES_TERMINAL VERBATIM) + add_dependencies(check-core check-oss-sdk-plugin) +else() + add_dependencies(check-core check-oss-sdk-construction) +endif() diff --git a/tests/osssdk/construction.cpp b/tests/osssdk/construction.cpp new file mode 100644 index 000000000..66f268649 --- /dev/null +++ b/tests/osssdk/construction.cpp @@ -0,0 +1,55 @@ +// Copyright (c) 2026 OpenArkStudio. Licensed under Apache-2.0. See LICENSE. +#include +#include +#include + +#include "../network/doctest.h" + +#include +#include +#include "oss_sdk_factory.hpp" + +#if __has_include() +#error "OSS SDK public mappings must exclude the private factory" +#endif + +static_assert(std::is_base_of_v, ark::oss_sdk_module_impl>); +static_assert(std::is_base_of_v, ark::oss_sdk_plugin>); +static_assert(std::is_same_v); +static_assert(std::is_same_v>); + +TEST_CASE("OSS SDK real factory retains its public implementation and unpublished metadata") { + auto candidate = ark::detail::make_oss_sdk_module(); + REQUIRE(candidate != nullptr); + const auto* instance = candidate.get(); + CHECK(typeid(*instance) == typeid(ark::oss_sdk_module_impl)); + CHECK(candidate->get_plugin_manager() == nullptr); + CHECK(candidate->get_name().empty()); +} + +TEST_CASE("OSS SDK assembly retains the interface key, disabled updates and explicit ownership") { + ark::plugin_manager manager; + ark::oss_sdk_plugin owner; + owner.set_plugin_manager(&manager); + CHECK(owner.get_plugin_version() == 0); + CHECK(owner.get_plugin_name() == typeid(ark::oss_sdk_plugin).name()); + owner.set_plugin_conf("oss-sdk-construction.toml"); + CHECK(ark::oss_sdk_plugin::get_plugin_conf() == "oss-sdk-construction.toml"); + owner.install(); + auto* instance = manager.find_module(); + REQUIRE(instance != nullptr); + CHECK(typeid(*instance) == typeid(ark::oss_sdk_module_impl)); + CHECK(instance->get_plugin_manager() == &manager); + CHECK(instance->get_name() == typeid(ark::oss_sdk_module).name()); + // Insertion succeeds only when assembly left the module out of the update set. + CHECK(manager.add_update_module(instance)); + manager.remove_update_module(instance->get_name()); + CHECK_THROWS_AS(owner.install(), std::runtime_error); + CHECK(manager.find_module() == instance); + owner.uninstall(); + // Reinstallation proves the public registration key and ownership were released. + CHECK_NOTHROW(owner.install()); + CHECK_NOTHROW(owner.uninstall()); + CHECK(manager.update(1)); + CHECK_THROWS_AS(owner.uninstall(), std::runtime_error); +} diff --git a/tests/osssdk/entry.cpp b/tests/osssdk/entry.cpp new file mode 100644 index 000000000..d32165f9a --- /dev/null +++ b/tests/osssdk/entry.cpp @@ -0,0 +1,45 @@ +// Copyright (c) 2026 OpenArkStudio. Licensed under Apache-2.0. See LICENSE. +#include +#include +#include + +#include +#include +#include + +namespace { + +void require(bool condition, const char* message) { + if (!condition) + { + std::cerr << message << std::endl; + std::_Exit(1); + } +} + +} // namespace + +int main(int argc, char* argv[]) { + require(argc == 3, "Expected OSS SDK entry-probe directory and library stem"); + ark::logger log; + ark::logger::init(&log); + log.set_log_func([](spdlog::level::level_enum, const std::string&) {}); + ark::dynamic_library library(argv[2]); + require(library.load(argv[1]), "Cannot load OSS SDK entry-probe library"); + auto events = reinterpret_cast(library.get_symbol("oss_sdk_entry_events")); + require(events && events(0) == 0 && events(1) == 0, "Entry-probe state is not fresh"); + require(library.get_symbol("DllEntryPlugin") && library.get_symbol("DllExitPlugin"), + "OSS SDK explicit entry/exit exports are missing"); + ark::plugin_manager manager; + require(manager.start(0, argv[1], "conf/", {{argv[2], "entry-probe.toml"}}), "OSS SDK explicit entry failed"); + auto* instance = manager.find_module(); + require(instance && instance->get_plugin_manager() == &manager && + instance->get_name() == typeid(ark::oss_sdk_module).name(), + "OSS SDK explicit entry lost interface registration metadata"); + require(events(0) == 1 && events(1) == 0, "OSS SDK entry did not transfer factory ownership"); + require(manager.update(1) && events(2) == 0, "OSS SDK entry changed disabled update selection"); + require(manager.stop(2) && events(1) == 1, "OSS SDK explicit exit did not destroy its module exactly once"); + require(manager.stop(3) && events(1) == 1, "Repeated stop invoked OSS SDK exit twice"); + require(library.unload(), "Cannot release OSS SDK observation handle"); + std::cout << "OSS SDK real assembly entry/exit, configuration, interface metadata and ownership passed\n"; +} diff --git a/tests/osssdk/entry_factory.cpp b/tests/osssdk/entry_factory.cpp new file mode 100644 index 000000000..b51dad2e7 --- /dev/null +++ b/tests/osssdk/entry_factory.cpp @@ -0,0 +1,55 @@ +// Copyright (c) 2026 OpenArkStudio. Licensed under Apache-2.0. See LICENSE. +#include + +#include +#include +#include "oss_sdk_factory.hpp" + +namespace { + +unsigned created{}; +unsigned destroyed{}; +unsigned updated{}; + +class entry_oss_sdk final : public ark::module_base +{ +public: + entry_oss_sdk() { + ++created; + } + + ~entry_oss_sdk() override { + ++destroyed; + } + + bool init() override { + return ark::oss_sdk_plugin::get_plugin_conf() == "conf/entry-probe.toml"; + } + + bool update() override { + ++updated; + return true; + } +}; + +} // namespace + +namespace ark::detail { + +std::unique_ptr make_oss_sdk_module() { + return std::make_unique(); +} + +} // namespace ark::detail + +ARK_EXPORT_FUNC unsigned oss_sdk_entry_events(unsigned event) { + switch (event) + { + case 0: + return created; + case 1: + return destroyed; + default: + return updated; + } +} diff --git a/tests/osssdk/exports.cpp b/tests/osssdk/exports.cpp new file mode 100644 index 000000000..118770b0b --- /dev/null +++ b/tests/osssdk/exports.cpp @@ -0,0 +1,31 @@ +// Copyright (c) 2026 OpenArkStudio. Licensed under Apache-2.0. See LICENSE. +#include +#include +#include + +#include + +namespace { + +void require(bool condition, const char* message) { + if (!condition) + { + std::cerr << message << std::endl; + std::_Exit(1); + } +} + +} // namespace + +int main(int argc, char* argv[]) { + require(argc == 3, "Expected plugin directory and library stem"); + ark::logger log; + ark::logger::init(&log); + log.set_log_func([](spdlog::level::level_enum, const std::string&) {}); + ark::dynamic_library library(argv[2]); + require(library.load(argv[1]), "Cannot load actual OSS SDK shared library"); + require(library.get_symbol("DllEntryPlugin") != nullptr, "Missing explicit DllEntryPlugin export"); + require(library.get_symbol("DllExitPlugin") != nullptr, "Missing explicit DllExitPlugin export"); + require(library.unload(), "Cannot unload OSS SDK shared library"); + std::cout << argv[2] << ": actual DSO load, explicit entry/exit exports and unload passed\n"; +}