尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Fluent-Bit 内嵌 lwrb 环形缓冲库测试体系详解:CMake、ctest、Sanitizers 与代码覆盖率实践

Fluent-Bit 内嵌 lwrb 环形缓冲库测试体系详解:CMake、ctest、Sanitizers 与代码覆盖率实践 Fluent-Bit 内嵌 lwrb 环形缓冲库测试体系详解CMake、ctest、Sanitizers 与代码覆盖率实践【免费下载链接】fluent-bitFast and Lightweight Logs, Metrics and Traces processor for Linux, BSD, OSX and Windows项目地址: https://gitcode.com/GitHub_Trending/fl/fluent-bit本文以 Fluent-Bit 仓库中 lwrbLightweight ring buffer轻量级环形缓冲库自带的测试套件文档为核心系统讲解该 C 语言库测试环境的搭建与运行方式如何通过 CMake 可选地启用 AddressSanitizer、UndefinedBehaviorSanitizer 与 lcov 代码覆盖率如何用 ctest 执行基于 Unity 框架的单元测试以及生成 HTML 覆盖率报告的完整流程。读完后你可以独立复现 lwrb 的测试环境并理解其 CMake 构建脚本背后的实现逻辑将这套方法迁移到其他纯 C 库的测试工作中。lwrb 库及其在 Fluent-Bit 中的定位lwrb 是 Fluent-Bit 仓库内置的一个通用 FIFO先入先出环形缓冲区实现位于 lib/lwrb/README.md 所描述的库根目录下。根据该库的 README它具备以下特征使用 ANSI C99 编写尺寸数据统一采用size_t平台无关不含任何架构相关的代码无动态内存分配数据存储在调用方提供的静态数组中使用优化的内存拷贝而非逐字节循环完成读写在单写单读的管道场景下具备线程安全与中断安全特性支持 DMA 传输、读侧 peek/skip、写侧 advance 以及事件通知。这些特性可以通过 lwrb 头文件 得到印证lwrb_t结构体仅包含一个数据指针、缓冲大小、读指针r、写指针w和事件回调函数并在首尾各放置一个 magic 字用于检测内存越界破坏LWRB_USE_MAGIC默认为开启typedef struct lwrb { uint32_t magic1; /*! Magic 1 word */ uint8_t* buff; /*! Pointer to buffer data */ LWRB_VOLATILE size_t size; /*! Size of buffer data */ LWRB_VOLATILE size_t r; /*! Next read pointer */ LWRB_VOLATILE size_t w; /*! Next write pointer */ lwrb_evt_fn evt_fn; /*! Pointer to event callback function */ uint32_t magic2; /*! Magic 2 word */ } lwrb_t;由于 Fluent-Bit 的数据流路径中存在对环形缓冲的需求核心源码 flb_ring_buffer.c 中直接调用了lwrb_init与lwrb_write来初始化并写入内部环形缓冲。正因如此为 lwrb 建立一套可重复、可度量的测试环境对整个日志处理器的稳定性都有直接意义。测试环境目录结构与要求测试环境的入口文档是 测试套件 README其所在目录lib/lwrb/lwrb/test/下共包含三个关键文件文件作用README.md测试环境的搭建与运行指南本文的主体来源test.c基于 Unity 框架的单元测试源码CMakeLists.txt测试工程的 CMake 构建脚本llvm-cov.shclang 环境下用llvm-cov gcov包装 lcov 的 gcov 工具根据 README 的 Requirements 一节构建该测试环境需要满足以下前提仓库需递归构建以拉取 git submodule。lwrb 的测试依赖第三方组件 UnityC 语言单元测试框架与 sanitizers-cmake二者按 测试 CMake 脚本 中的路径定义位于lib/lwrb/third_party/下set(THIRD_PARTY_DIR ${CMAKE_SOURCE_DIR}/../../third_party) set(UNITY_DIR ${THIRD_PARTY_DIR}/Unity) set(LWRB_DIR ${CMAKE_SOURCE_DIR}/../src)从源码结构看当前仓库快照中lib/lwrb/third_party/目录尚未检出正是因为它由 git submodule 管理需要执行递归 clone 或git submodule update --init --recursive类操作才能获得。必须安装 CMake。测试工程通过cmake_minimum_required(VERSION 3.0)声明最低版本要求而仓库顶层的 CMakePresets.json 使用了 preset version 3要求 CMake 3.20并默认采用 Ninja 生成器同时提供了Win32-Debug与Win64-Debug两个基于 MinGW 工具链cmake/i686-w64-mingw32-gcc.cmake、cmake/x86_64-w64-mingw32-gcc.cmake的交叉编译预设。如需启用 Sanitizers编译器必须提供对应的 sanitizer 运行库。AddressSanitizerASan与 UndefinedBehaviorSanitizerUBSan需要 gcc 或 clang 携带 sanitizer 依赖才能链接成功。如需覆盖率统计还需安装 gcov 与 lcov。构建测试工程CMake 命令与可选参数README 给出的标准构建流程如下mkdir build cd build cmake -DSANITIZE_ADDRESSOn -DSANITIZE_UNDEFINEDOn -DWITH_COVERAGEOn .. make -j其中三个 CMake 选项的含义可以从 测试 CMake 脚本 中逐一确认-DWITH_COVERAGEOn开启后脚本会先探测llvm-cov是否存在若 C 编译器是 clang含 AppleClang且找到了llvm-cov则把 lcov 使用的 gcov 工具替换为本目录下的 llvm-cov.sh。该脚本只有一行实质内容——exec llvm-cov gcov $其作用是让 lcov 在 clang 环境下用llvm-cov的 gcov 兼容模式解析覆盖率数据。随后脚本include(CodeCoverage)并调用append_coverage_compiler_flags()向编译单元追加-fprofile-arcs -ftest-coverage类插桩标志。-DSANITIZE_ADDRESSOn/-DSANITIZE_UNDEFINEDOn这两个开关由find_package(Sanitizers)加载的 sanitizers-cmake 模块消费最终通过add_sanitizers(lwrb_test)作用于测试可执行文件。README 明确指出这两个参数是可选的加上它们有利于发现更多潜在 bug如越界读写、未定义行为但如果本机没有安装 sanitizer 库可以直接丢弃这两个参数而不影响测试本身。构建目标lwrb_test由三部分源文件组成add_executable(lwrb_test test.c ${LWRB_DIR}/lwrb/lwrb.c ${UNITY_DIR}/src/unity.c) target_include_directories(lwrb_test PRIVATE ${LWRB_DIR}/include ${UNITY_DIR}/src)即单元测试源码test.c 被测库实现 lwrb.c Unity 框架本体unity.c头文件搜索路径则同时指向库的include目录与 Unity 源码目录。最后通过add_test(lwrb_test_suite lwrb_test)将该可执行文件注册到 CTest 测试框架。运行单元测试ctest 与 5 个测试用例README 提供的运行方式很直接# 在之前创建的 build 目录内执行 ctest # 或等价地 make test真正被执行的测试逻辑位于 test.c。该文件使用 Unity 框架编写main()中依次注册了 5 个测试用例int main (void) { UNITY_BEGIN(); RUN_TEST(testNullInputToInit_should_fail); RUN_TEST(testNormalInputToInit_should_succeed); RUN_TEST(testAddElementsToQueueAndRead_should_succeed); RUN_TEST(testAddElementsToQueueAndReadAndVerifyEmpty_should_succeed); RUN_TEST(testAddElementsToQueueAndReadTooSmallBuffer_should_fail); return UNITY_END(); }各用例分别覆盖的断言点如下testNullInputToInit_should_failtest.c#L35-L52向lwrb_init传入 NULL 的缓冲控制结构、NULL 的数据区或长度为 0 的数据区均要求返回 0失败随后lwrb_is_ready也应返回 0验证失败初始化不会留下就绪状态。testNormalInputToInit_should_succeedtest.c#L54-L65用 1 字节数据区正常初始化lwrb_init与lwrb_is_ready均应返回 1。testAddElementsToQueueAndRead_should_succeed与 4.testAddElementsToQueueAndReadAndVerifyEmpty_should_succeed二者共用辅助函数basic_read_and_writetest.c#L117-L142其流程为分配数据量 1 字节的缓冲多出的 1 字节用于区分满/空状态→lwrb_init→ 校验lwrb_is_ready→lwrb_write写入 8 字节序列{0..7}→ 用lwrb_get_full校验已用空间 →lwrb_read读出并用TEST_ASSERT_EQUAL_UINT8_ARRAY逐字节比对读回数据。第 4 个用例额外断言读空后lwrb_get_free返回的可用空间等于全部写入量。testAddElementsToQueueAndReadTooSmallBuffer_should_failtest.c#L84-L100将数据区大小设为恰好等于待写入长度不预留区分满/空的额外字节断言lwrb_write只能写入数据量 - 1字节验证环形缓冲实际容量比声明少 1 字节的边界行为。从这组用例可以看出测试聚焦于 API 契约的边界条件非法入参、容量语义、数据一致性与 lwrb 无动态分配、静态数组的设计直接对应。生成并查看代码覆盖率报告README 的 Coverage output 一节给出# 在之前创建的 build 目录内执行 # 若计划运行本命令配置 cmake 时不要使用 ninja make coverage # 假定 Linux 主机上已安装 Google Chrome google-chrome coverage/index.html # 查看 HTML 格式的覆盖率报告结合 测试 CMake 脚本 的实现可以补全这条命令背后的机制if(WITH_COVERAGE) setup_target_for_coverage_lcov( NAME coverage EXECUTABLE ctest EXCLUDE ${CMAKE_SOURCE_DIR}/* ${THIRD_PARTY_DIR}/*) endif(WITH_COVERAGE)setup_target_for_coverage_lcov是 sanitizers-cmake 仓库附带的 CodeCoverage 模块提供的宏它会生成名为coverage的 make 目标先执行ctest让插桩代码运行起来产生.gcda计数文件再调用 lcov 汇总生成coverage/index.html并通过EXCLUDE规则把测试自身源码目录与第三方目录Unity、sanitizers-cmake从统计范围中剔除使报告只反映被测库lwrb.c的覆盖情况。README 特别提示不要使用 ninja 配置 cmake原因在于 lcov 覆盖率流程依赖 make 目标机制.gcno/.gcda文件的清理与重生成而 Ninja 生成器不生成可被该流程驱动的 Makefilemake coverage将不可用。另外对于 clang/AppleClang 用户llvm-cov.sh的引入解决了 lcov 默认调用gcov无法解析 clang 覆盖率数据的问题——CMake 脚本在检测到 clang 系编译器且系统存在llvm-cov时自动将GCOV_PATH指向该包装脚本这一步在make coverage时静默生效使用者无需额外配置。测试基础设施的补充细节除 README 正文外目录内还有几处值得注意的工程细节Windows 交叉编译预设CMakePresets.json 定义了Win32-Debug与Win64-Debug两个 preset分别通过cmake/i686-w64-mingw32-gcc.cmake与cmake/x86_64-w64-mingw32-gcc.cmake工具链文件实现 MinGW 交叉构建验证了该库平台无关声明在 Windows 目标上同样可编译。由于测试工程本身是独立的 CMake 项目project(lwrb-testing)在 lwrb 目录内执行cmake --preset Win64-Debug配置的是顶层开发工程链接 dev/main.c 的调试可执行文件而测试套件仍按上文流程单独配置。顶层工程与测试工程的分工lib/lwrb/CMakeLists.txt 仅在作为顶层项目时启用注释说明其用途是 standalone 编译内部通过add_subdirectory(lwrb)复用库的 lwrb/CMakeLists.txt当 lwrb 被 Fluent-Bit 等其他项目以子目录方式纳入时使用的则是后者的库构建定义。测试工程lwrb/test/CMakeLists.txt则直接以源文件形式编译lwrb.c不依赖共享库产物保持测试的自包含性。README 中的 Future work原文档最后提到计划将该测试接入 CI 环境并把测试结果与覆盖率以 banner 形式回显到仓库说明该测试体系仍处于持续完善阶段。小结lwrb 的测试套件是一个小而完整的 C 语言库测试参考实现以 CMake CTest 为骨架用 Unity 框架编写边界导向的单元测试通过 sanitizers-cmake 可选接入 ASan/UBSan再用 lcov 产出剔除第三方噪声后的 HTML 覆盖率报告并通过llvm-cov.sh兼容 clang 工具链。对于需要在 Fluent-Bit 仓库内验证环形缓冲行为或希望为其他纯 C 库搭建同等质量测试环境的工作者测试目录 下的四个文件README、test.c、CMakeLists.txt、llvm-cov.sh提供了可直接对照复现的全部依据。【免费下载链接】fluent-bitFast and Lightweight Logs, Metrics and Traces processor for Linux, BSD, OSX and Windows项目地址: https://gitcode.com/GitHub_Trending/fl/fluent-bit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表