功能测试验证正确性,持续压力测试检查重复工作、重启与清理。 性能测量在这些检查通过后于本机执行,使用不带 Sanitizer 的 Release 构建。 CI 用于回归和冒烟执行,共享 runner 的时间不作为发布的性能基线。
下载验证日志与源码对应关系及 SHA256 校验和。归档包含双语说明和独立校验工具。
构建与执行
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release \
-DARKNET_ENABLE_SSL=ON -DARKNET_BUILD_TESTS=ON \
-DARKNET_BUILD_BENCHMARKS=ON -DARKNET_USE_BOOST_ASIO=ON
cmake --build build --parallel 3
cmake --build build --target arknet_check
build/tests/arknet_stress_test --protocol all --seconds 60 \
--clients 16 --rounds 2 --window 4 --certs tests/certs使用 Standalone Asio 时,在独立构建目录设置
-DARKNET_USE_BOOST_ASIO=OFF -DARKNET_ASIO_INCLUDE_DIR=/path/to/asio/include。
HTTP 和 WebSocket 检查依赖 Boost.Asio 与 Boost.Beast,因此两种配置的检查数量不同。
Windows 可执行文件带 .exe 后缀。
仓库提供的 TLS 证书仅用于测试,不用于生产身份。
测试使用 doctest 2.5.3,源文件保存在 tests/vendor/doctest,
不会安装,也不成为应用依赖。arknet_check 直接执行测试程序、
安装包消费项目和已启用的基准冒烟用例,设置超时,并将日志写入
build/tests/logs/,不使用 CTest。
build/tests/arknet_tcp_test --list-test-cases
build/tests/arknet_tcp_test --test-case="*framing*"
build/tests/arknet_tls_test --reporters=junit --out=build/tls.xml功能测试和性能基准都是包含独立 main 的 C++ 程序,编译后直接运行。
这些 C++ 功能测试和单项基准不需要 Python、Ruby、jq、GNU timeout 或 shasum。
正确性覆盖
| 测试组 | 内容 |
|---|---|
| TCP/UDP/WebSocket | 拆包、二进制/空数据、自定义 Session、端点路由、重连和发送所有权 |
| HTTP/router | 独立 raw 对端的 chunked/HEAD/Expect、有序流水线、上限、方法/路径、中间件、错误和 HTTP/HTTPS 绑定 |
| HTTP 请求 | 独立 raw 对端、HEAD/临时/chunked/EOF 响应、取消、截止时间、上限与完成回调恰好执行一次 |
| ARQ/RUDP | 原版协议互通、丢失/乱序、内存上限、握手重试、IPv4/IPv6、旧 SYN 处理和关闭 |
| FEC/RUDP FEC | 独立 Reed–Solomon 实现互通、协商、CRC 拒绝、重复与重放、恢复、不完整分组、内存预算、固定/自适应策略和并发统计 |
| lifecycle/detail/IO pool | timer/post 取消、实际完成后销毁、mutable 监听器、执行器串行化、排队任务和重启 |
| 进程退出/线程存储 | 回调释放最后一个所有者、嵌套线程池、直接及间接全局所有权、两种跨编译单元链接顺序、退出后拒绝构造及保留显式 Asio 配置 |
| concurrency/keepalive | 发送配额、回调完成计数、并发停止和 TCP keepalive |
| TLS | 信任/身份拒绝、mTLS、截止时间、WSS 和重连时创建新 stream |
| IPv6 | TCP、UDP/session/cast、WS/WSS、HTTP/HTTPS、TLS IP 身份验证和握手 Host |
| MySQL | 报文/认证/命令编解码、TLS 身份验证、查询、预处理、事务、结果上限、取消、有界准入,以及独占连接池的重置与数据库隔离 |
| Redis | RESP2/RESP3、认证、TCP/TLS/mTLS、有序流水线、取消后的回复排空、有界准入、拒绝复制命令,以及独占连接池的重置、认证与数据库隔离 |
| 安装包消费项目 | 依赖方案/TLS 配置传播与已安装公开头文件 |
持续压力测试验证数据与序号、完成计数、连接/服务端重启、未完成写入和队列清理。
每种协议将 --seconds 分配给四种配置:库内置调度器、单 context 单线程、
单 context 四线程、四个 context 各一线程,再分给指定重启轮次。因此七种协议使用 --seconds 60
时,请求的流量阶段共七分钟,另加启动和收尾。慢接收者用例测试背压,不用于比较吞吐量。
本机验证
完整测试的源码快照为 6c8418e,其中的网络库改动已纳入性能测量版本
2aa5bc0。分开验证的纯测试改动 25bb9f8 覆盖下文的分配失败可移植性和
原生连接完成顺序。连接池关闭专项单独标识源码快照 550fb58。
PR #16
记录候选版本审查与跨平台 CI;本机结果不代替候选版本自身的检查。
验证日期为 2026-10-15 至 16 日。机器为 Mac mini Mac16,11、Apple M4 Pro、14 个物理/逻辑核心
(10 个性能核心、4 个能效核心)、48 GiB 内存、macOS 27.0.1(26A434)。
依赖为 Standalone Asio 1.38.2、Boost 1.90.0 和 OpenSSL 3.6.4。
普通构建使用 Apple Clang 21.0.0,Sanitizer 构建使用 LLVM 22.1.7。
完整检查
四套构建均使用 Debug,启用 TLS 和测试,关闭示例与基准程序。 全部编译完成后,使用真实数据库服务串行执行检查。
| 依赖/检测工具 | 检查数 | doctest 用例数 | 断言数 | 结果 |
|---|---|---|---|---|
| Boost.Asio | 52/52 | 470 | 978,433 | 通过 |
| Standalone Asio | 51/51 | 410 | 576,824 | 通过 |
| Boost.Asio/ASan+UBSan | 52/52 | 470 | 615,937 | 通过 |
| Standalone Asio/TSan | 51/51 | 410 | 333,108 | 通过 |
检查数是 arknet_check 执行的程序数,用例数是 doctest 执行的用例数。
断言数为实际执行计数,包含按时长运行的压力用例。
已启用的默认测试组均无失败或环境条件导致的跳过。本轮未启用归档的 Zephyr 互通测试,
其独立证据见下文;默认测试包含独立 ARQ/FEC 实现互通。
每套配置均包含外部 context 停止(15 个用例/375 项断言)、排队连接取消(4/44)、 协议、运行时退出、压力测试和安装包使用检查。 安装包消费项目的子构建不继承 Sanitizer 参数,因此不计为 Sanitizer 覆盖。
数据库与停止行为覆盖
四套配置均使用隔离的 MySQL Community 8.4.11 和 Redis 7.4.2 执行可选真实服务用例,
没有跳过数据库用例。MySQL 验证 TLS,Redis 覆盖 TCP、TLS 和 mTLS。
测试包含连接/客户端与连接池操作、永久关闭 close_and_wait()、晚到连接、
回调与捕获对象释放、任务提交失败及恢复、取消和重置隔离。
未提供服务环境变量时,真实服务用例会跳过,不会用模拟服务代替。
Redis 协议的性能测量使用 Valkey 8.0.11,与这里的 Redis 7.4.2 互通验证分开记录。
基于 TCP 的端点验证原生操作完成和捕获对象释放;多个所有者同时完整停止的串行化保证 限定于 TCP 服务端及其 HTTP/WebSocket/TLS 派生服务端,不扩大为所有协议的新保证。 外部 context 的所有者须先停止外部提交方,并在排空期间保持执行线程运行; 工作线程中的回调不能阻塞等待自身退出。详见生命周期与 正式停止及故障用例。 这些结果不构成动态库可安全卸载的验证。
补充专项检查
| 范围 | 检查数 | 用例数 | 断言数 | 结果 |
|---|---|---|---|---|
| Boost.Asio、关闭 TLS:八个指定目标 | 8/8 | 66 | 1,515 | 通过 |
| Boost.Asio ASan+UBSan:排队连接、HTTP 外部 context 与外部停止重复执行 | 72/72 | 280 | 4,664 | 通过 |
无 TLS 检查覆盖 TCP、外部停止、manual-runtime、排队连接取消,以及四个 Redis 停止/任务提交失败目标;不代表完整无 TLS 矩阵,也不代表 MySQL 可以不依赖 OpenSSL。 72 次 ASan 执行包括 32 次排队连接测试、32 次指定 HTTP 用例及八次外部停止测试。 HTTP 显式过滤器排除的用例不属于环境条件导致的跳过;完整 HTTP 测试组已在上表通过。
纯测试改动的分配失败与连接顺序验证单独记录:
| 依赖/检测工具 | 专项用例数 | 断言数 | 指定原生错误用例执行次数 |
|---|---|---|---|
| Boost.Asio/ASan+UBSan | 30 | 927 | 32/32 通过 |
| Standalone Asio/ASan+UBSan | 30 | 927 | 32/32 通过 |
| Boost.Asio/TSan | 30 | 926 | 32/32 通过 |
| Standalone Asio/TSan | 30 | 926 | 32/32 通过 |
全部专项用例通过,未出现 Sanitizer 诊断。指定原生错误用例共执行 128 次, 每次检查九项断言;过滤器排除的其他用例不属于环境条件导致的跳过。 这些记录补充完整源码快照的结果,不代表纯测试改动的整套检查结果。 MSVC 专用 CRT 分配路径在 Windows CI 中执行,本机 macOS 验证不覆盖该路径。
连接池关闭检查
源码快照 550fb58 在两种连接池中原位排空 acquire 等待请求,避免
unordered_map 移动构造依赖分配。正式回归覆盖两个排队请求、回调重入
close/cancel/acquire、完成通知恰好执行一次及捕获释放。测试使用拥有者侧关闭守卫,
在致命断言导致退出时先永久关闭连接池,再销毁回调引用的状态。
| 依赖/检测工具 | MySQL 关闭用例/断言 | Redis 关闭用例/断言 |
|---|---|---|
| Boost.Asio/ASan+UBSan | 14/1,067 | 19/596 |
| Standalone Asio/ASan+UBSan | 14/1,067 | 19/596 |
| Boost.Asio/TSan | 14/1,067 | 19/595 |
| Standalone Asio/TSan | 14/1,066 | 19/595 |
八次目标程序执行均通过,无失败、跳过或 Sanitizer 诊断。四套配置另通过未改动的 MySQL 归还失败测试(5 个用例/222 项断言)与 Redis 归还失败测试(4/107)。 归还失败检查在仅调整测试关闭守卫之前执行,其测试文件和两个连接池头文件与本快照相同。 这些是专项检查,不是本快照的完整测试运行。
Redis 诊断测试将被检查的异常快照保留到并发观察线程退出。验证归档保留原 Linux TSan、
Windows 故障注入失败记录、源码对应关系和专项日志。连接池修正移除了一处分配边界,
不保证所有子连接关闭路径都能从堆内存耗尽中恢复。性能测量继续对应这项关闭修正之前的
2aa5bc0。
本机 macOS ASan 关闭泄漏检测。完整检查的 ASan 还关闭了在线符号化,以避开已定位的
符号化程序挂起问题,内存检测仍然启用。没有新增 Sanitizer 抑制规则或强制预包含参数。
仅沿用原版 KCP 测试编译单元的 null,object-size 检测排除项。
RUDP 互通专项证据
以下专项执行记录于 2026-10-13,源码版本与范围保留在链接记录中; 其中较早的完整检查计数不代表当前项目。
| 检测工具 | 范围 | 用例 | 结果 |
|---|---|---|---|
| ASan/UBSan | Standalone Asio:ARQ、独立 ARQ/FEC 实现互通、RUDP/FEC、lifecycle、detail 与 concurrency | 109 | 通过 |
| TSan | Standalone Asio:FEC、独立 FEC 实现互通、RUDP/FEC、lifecycle、detail 与 concurrency | 86 | 通过 |
RUDP FEC 端点测试在两种 Release 依赖方案及独立 ASan/UBSan、TSan 构建中均通过 11 个用例、 2,564 项断言。真实 zephyr/arknet 混合进程测试每种依赖方案均通过 12 组,覆盖重连、ARK 二进制 消息头、4096 字节消息体、ARQ 报文丢失和乱序。中继保留 SYN/ACK/FIN,未验证 FIN 丢失后的可靠关闭。
日志与复现命令
记录了源码版本和检查范围。仅用于测试的原版 KCP 源码关闭 null,object-size 检测,
arknet 自有代码保留完整检测。性能数据见独立的 RUDP 报告。
Sanitizer 单独执行,不混入性能测量。LeakSanitizer 的支持依平台而异; Apple ASan 通过不等同于 Linux 泄漏检查通过。
Sanitizer 检查
Sanitizer 在开发构建中插入检测代码,报告测试运行时发现的错误。
| 工具 | 检查范围 |
|---|---|
| ASan(AddressSanitizer) | 内存错误,例如越界访问、释放后继续访问和重复释放 |
| TSan(ThreadSanitizer) | 未正确同步的并发内存访问,且至少一次访问是写入 |
| UBSan(UndefinedBehaviorSanitizer) | 部分未定义行为,例如有符号整数溢出、无效移位和未对齐访问 |
ASan/UBSan 与 TSan 使用独立构建。它们会增加运行开销,发布的性能测量关闭这些 工具。测试通过只覆盖本次执行的代码路径和线程调度,不能证明所有错误都不存在。
CI 与未覆盖范围
CI 在 Linux/macOS/Windows 检查两种依赖方案,Linux 另运行 ASan/UBSan 和 TSan。 Job 名称包含系统、依赖方案、TLS 和检查模式。PR、合并队列候选和手动触发均运行完整 14 项检查。PR 源分支通过,不代表包含最新 main 和前序队列改动的候选已经通过。 候选合入 main 后,不重复运行同一套矩阵。README 徽章展示合并队列运行结果。
运行保留现有的 PR 或 ref 并发组。新运行不会取消同组内正在执行的运行,而是等待并发组。 GitHub 仍可能替换同组较早的待执行运行,因此这个设置不保证每次 push 都按 FIFO 顺序保留, 详见 GitHub 并发规则。 候选的必需检查仍须全部通过。文档发布继续使用独立的 main push 工作流。 CI 上传测试日志、执行基准冒烟;性能报告矩阵来自本机测量。
本机 RUDP 测量覆盖随机/突发丢包、延迟、重复与乱序,并包含六组 120 秒持续运行。 这些结果不能预测跨主机容量和广域网延迟。文件描述符耗尽、生产时长耐久及 ARK 业务验收仍需单独验证。
文档中的 14 个独立客户端、服务端程序也在两种依赖方案上编译、运行通过。每种依赖方案 的七组协议检查了回显内容,全部 28 个进程正常退出。 构建、运行日志与复现脚本 独立保留这项检查,不混入性能测量。