多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

OpenZFS ZFS Test Suite 完全指南:构建、运行与自定义测试用例实战

OpenZFS ZFS Test Suite 完全指南:构建、运行与自定义测试用例实战 操作系统【免费下载链接】zfsOpenZFS on Linux and FreeBSD项目地址https://gitcode.com/gh_mirrors/zf/zfs点击查看免费下载导读ZFS Test SuiteZTS是 OpenZFS 项目自带的端到端测试框架覆盖 zfs/zpool 命令行、ARC 缓存、快照、加密、zvol、故障处理等上百个功能模块用于在 Linux 与 FreeBSD 上系统化验证 ZFS 行为。本文以仓库内的 tests/README.md 为骨架结合 scripts/zfs-tests.sh 与 tests/test-runner/bin/test-runner.py.in 的源码实现完整讲解测试套件的构建安装、运行前置条件、zfs-tests.sh全部选项、runfile 与 tags 筛选机制、结果日志解读并手把手演示如何新增一个属于自己的测试用例zpool_example。读完本文你将能够在自己的 ZFS 环境中跑通整套测试、精准定位并运行单个用例、读懂测试结果并具备为 OpenZFS 贡献新测试用例的完整能力。一、ZFS Test Suite 总体架构ZFS Test Suite 运行在名为test-runner的框架之上。从源码结构看整个测试体系由三层组成test-runner 执行引擎Python 实现的 test-runner.py负责读取 runfile、调度测试、执行超时控制、汇总结果启动包装脚本Bash 实现的 scripts/zfs-tests.sh负责环境探测、磁盘准备、约束 PATH、调用 test-runner 并汇总报告测试用例与 runfile位于 tests/zfs-tests/tests/functional 下按功能模块组织的数百个.ksh测试脚本以及 tests/runfiles 下描述跑哪些测试的.run配置文件。test-runner 与标准 ZFS 工具一同构建并被打包进zfs-test包中。仓库内 tests/runfiles 目录实际提供了common.run、linux.run、freebsd.run、sunos.run、sanity.run、longevity.run、perf-regression.run、bclone.run等多套运行清单分别面向通用功能、各操作系统专属用例、快速冒烟、长稳与性能回归等不同场景。二、构建并安装 zfs-test 包2.1 从源码构建在完成 ZFS 源码树的./configure之后构建测试套件只需一条命令$ ./configure $ make pkg-utilsmake pkg-utils会生成zfs-test相关的安装包。产物.rpm或.deb可按发行版选择对应的包管理命令安装从源码安装时$ rpm -ivh ./zfs-test*.rpm # 或 $ dpkg -i ./zfs-test*.deb如果你的发行版仓库已提供zfs-test包即 ZFS 并非自源码安装也可以直接用包管理器安装$ yum install zfs-test # 或 $ apt-get install zfs-test2.2 包内包含什么安装后测试套件的关键资源落在以下标准路径对应仓库内的tests/目录安装路径作用对应仓库路径/usr/share/zfs/zfs-tests.sh启动脚本scripts/zfs-tests.sh/usr/share/zfs/test-runnertest-runner 框架tests/test-runner/usr/share/zfs/zfs-tests测试用例套件tests/zfs-tests/usr/share/zfs/runfilesrunfile 清单tests/runfiles三、运行前置条件根据 tests/README.md 与 scripts/zfs-tests.sh 的校验逻辑运行测试前必须满足以下条件三块空白测试盘。通过$DISKS环境变量以空格分隔指定例如DISKSvdb vdc vdd。若未指定zfs-tests.sh默认构造三个 loopback 设备用于测试DISKSloop0 loop1 loop2。从源码看脚本默认会在$FILEDIR默认/var/tmp下创建三个稀疏文件file-vdev0、file-vdev1、file-vdev2默认大小FILESIZE4G再通过losetupLinux见 scripts/zfs-tests.sh或mdconfigFreeBSD挂接为 loop 设备若指定-f则直接使用稀疏文件本身。脚本会校验磁盘数量非性能模式下NUM_DISKS少于 3 将直接报错Not enough disks (N/3 minimum)见 scripts/zfs-tests.sh。一个非 root 用户拥有完整基础权限并能通过sudo(8)免密切换到 root 来运行测试。这是硬性要求脚本开头就检查id -u若以 root 直接运行会立即失败并提示 This script must not be run as root.同时校验sudo id -un必须返回 root见 scripts/zfs-tests.sh。指定要保留的池。将不希望被测试触碰的池以空格分隔写入$KEEP变量。测试开始时会自动把系统上检测到的所有池加入保留列表。源码实现为若未设置KEEP脚本自动执行zpool list -Ho name收集全部现存池若一个都没有则兜底为rpool随后将其导出为内部变量__ZFS_POOL_EXCLUDE传给测试进程见 scripts/zfs-tests.sh。强烈建议使用专用测试机VM 亦可。因为测试套件会向测试机器添加用户和用户组以验证相关功能残留状态可能影响生产环境。FreeBSD 特有mountd(8)必须使用/etc/zfs/exports作为导出文件之一。默认情况下在/etc/rc.conf中设置zfs_enableyes即可。四、运行测试套件4.1 两种运行模式前置条件满足后直接运行安装好的启动脚本$ /usr/share/zfs/zfs-tests.sh另一种方式是从源码树直接运行便于开发者快速验证自己的修改。此模式下测试会使用源码树中的 ZFS 工具与内核模块而非系统已安装版本$ ./scripts/zfs-tests.sh需要注意的是为避免某些类型的失败源码树模式要求系统已安装 ZFS 的udev 规则可手动安装或确保系统上已装有某个版本的 ZFS。从源码结构看脚本会通过constrain_path见 scripts/zfs-tests.sh构建一个受限 PATHINTREE模式下将$(top_builddir)/tests/zfs-tests/bin设为约束路径并把$CMD_DIR下的标准 zfs 工具与tests/zfs-tests/cmd下的测试专用工具软链接进去确保测试调用的是源码树版本而非系统版本。4.2 zfs-tests.sh 选项全解README 列出以下核心选项结合 scripts/zfs-tests.sh 的getopts解析L400-L483与 usage 输出L344-L398整理成下表选项说明-v详细输出。调用 test-runner 前会额外记录测试环境信息包括所用 runfile、目标 DISKS、要保留的池等-q静默模式。传递给 test-runner仅在控制台输出未通过的测试与结果汇总-x清理所有 testpool、dm、loop 与文件不安全。会尝试销毁任何名为testpool的池、未使用的 DM 设备以及由 file-vdev 支撑的 loopback 设备。该操作可能误删与测试无关的资源仅限专用测试环境使用-k测试失败后禁止清理。test-runner 退出时不做额外清理便于保留现场分析特定测试-f直接使用稀疏文件而非 loopback 设备。此模式下依赖真实块设备的测试会被跳过-c仅创建并填充受限 PATH 后退出-I NUM迭代次数默认 1源码校验必须大于 0-d DIR在 DIR 目录中为 vdev 创建稀疏文件默认/var/tmp/该目录必须可被所有用户写world-writable-s SIZE使用 SIZE 大小的 vdev默认4G-r RUNFILES运行 RUNFILES 中的测试默认common.run,linux.run脚本按uname自动拼接-t PATH运行 test suite 下相对 PATH 的单个测试-T TAGS以逗号分隔的 tags 列表默认functional-u USER以 USER 身份运行单个测试默认 root此外从 scripts/zfs-tests.sh 的 usage 可见 README 之外还支持以下选项供高级调试与 CI 场景使用选项说明-h显示帮助-DDebug 模式立即显示所有测试输出比较嘈杂-K将测试名记录到/dev/kmsg-O测试超时时将调试信息 dump 到/dev/kmsg-S启用 stack tracer对性能有负面影响-R自动重跑失败的测试-m启用 kmemleak 报告仅 Linux-n NFSFILE使用 NFSFILE 文件确定 NFS 配置4.3 环境变量速查DISKS空格分隔的测试盘列表未设置时脚本自动创建 loop 设备loop0 loop1 loop2。KEEP空格分隔的需要保留的池未设置时自动收集系统全部现存池。RUNFILES、FILEDIR、FILESIZE、ITERATIONS、TAGS等均有同名选项对应也都可以通过环境变量覆盖见 scripts/zfs-tests.sh 的默认值定义。五、用 runfile 与 tags 选择测试子集ZFS Test Suite 允许通过runfile或tags 列表两种方式指定要运行的测试子集。5.1 runfile 格式runfile 的格式在test-runner(1)手册中有详细说明zfs-tests.sh使用的 runfile 可在/usr/share/zfs/runfiles下参考。仓库内的 tests/runfiles/common.run 是真实示例其结构为 INI 风格[DEFAULT] pre setup quiet False pre_user root user root timeout 600 post_user root post cleanup failsafe_user root failsafe callbacks/zfs_failsafe tags [functional] [tests/functional/alloc_class] tests [alloc_class_001_pos, alloc_class_002_neg, ...] tags [functional, alloc_class][DEFAULT]段定义全局默认行为setup/cleanup前后置脚本、运行用户、600 秒超时、失败兜底回调等每个[tests/functional/...]段则为一个测试目录组tests [...]列出该组要执行的用例名tags为该组打上的标签首个标签通常是functional。要使用自定义 runfile用-r指定$ /usr/share/zfs/zfs-tests.sh -r my_tests.runzfs-tests.sh的find_runfile会依次尝试$RUNFILE_DIR/name、$RUNFILE_DIR/name.run、name、name.run四种变体来定位文件见 scripts/zfs-tests.sh所以-r linux与-r linux.run均可命中仓库内的linux.run。5.2 tags 筛选如果不指定 runfile可以设置 tags 只运行特定测试$ /usr/share/zfs/zfs-tests.sh -T zpool_add此外-T还支持分数形式如1/3、2/3用于把全部测试按 tag 均分给多台执行机并行跑。源码中split_tags会先汇总各 runfile 中的 tags、去重、剔除functional再按NR % den num - 1取模选出对应份见 scripts/zfs-tests.sh保证每份测试交错分布。5.3 运行单个测试-t选项可以按路径或名称精确定位单个测试。按路径时需相对测试套件根目录例如$ ./scripts/zfs-tests.sh -t tests/functional/cli_root/zfs_bookmark/zfs_bookmark_cliargs.ksh也可以只给名字脚本会在整个套件中按名字查找$ ./scripts/zfs-tests.sh -t zfs_bookmark_cliargs源码实现中-t与-T互斥若传入的是名字而非路径会通过find $STF_SUITE -name $SINGLETEST*定位用例单个测试运行时zfs-tests.sh会在$FILEDIR下动态生成一个临时 runfile含pre/post的setup/cleanup脚本探测再交给 test-runner 执行见 scripts/zfs-tests.sh。六、测试结果解读6.1 输出格式测试运行时每个测试结束会打印一行信息全部结束后输出结果汇总其中包含完整日志的位置形如/var/tmp/test_results/[ISO 8601 日期]。一次带-v的正常运行大致如下取自 tests/README.md 的示例$ /usr/share/zfs/zfs-tests.sh -v -d /tmp/test --- Configuration --- Runfile: /usr/share/zfs/runfiles/linux.run STF_TOOLS: /usr/share/zfs/test-runner STF_SUITE: /usr/share/zfs/zfs-tests STF_PATH: /var/tmp/constrained_path.G0Sf FILEDIR: /tmp/test FILES: /tmp/test/file-vdev0 /tmp/test/file-vdev1 /tmp/test/file-vdev2 LOOPBACKS: /dev/loop0 /dev/loop1 /dev/loop2 DISKS: loop0 loop1 loop2 NUM_DISKS: 3 FILESIZE: 4G ITERATIONS: 1 TAGS: functional Keep pool(s): rpool /usr/share/zfs/test-runner/bin/test-runner.py -c /usr/share/zfs/runfiles/linux.run \ -T functional -i /usr/share/zfs/zfs-tests -I 1 Test: /usr/share/zfs/zfs-tests/tests/functional/arc/setup (run as root) [00:00] [PASS] ...more than 1100 additional tests... Test: /usr/share/zfs/zfs-tests/tests/functional/zvol/zvol_swap/cleanup (run as root) [00:00] [PASS] Results Summary SKIP 52 PASS 1129 Running Time: 02:35:33 Percent passed: 95.6% Log directory: /var/tmp/test_results/20180515T054509--- Configuration ---段由zfs-tests.sh的-v打印把运行环境完整暴露出来所用 runfile、test-runner 与套件路径、约束 PATH、稀疏文件、loopback、磁盘数、文件大小、迭代次数、tags 以及保留的池方便排查环境差异。6.2 结果状态机从 tests/test-runner/bin/test-runner.py.in 的Result类L75-L112可以看出每个测试的判定逻辑PASS进程退出码为 0SKIP退出码为 4例如-f文件模式下依赖真实块设备的测试即属此类FAIL其他非零退出码或检测到 kmemleak 泄漏输出KILLED测试超时被强制终止RERAN该测试被重跑过配合-R自动重跑机制。timeout 默认在 runfile 的[DEFAULT]段设置为 600 秒test-runner 的Cmd类兜底超时为 60 秒L179-L180按墙钟时间计时。完整日志统一写入/var/tmp/test_results/源码中BASEDIR /var/tmp/test_results见 L43下以 ISO 8601 时间戳命名的目录。七、实战新增并运行一个测试用例zpool_example以 tests/README.md 的zpool_example为例新增一个测试用例可以归纳为5 个步骤为运行测试的用户配置免密 sudo修改configure.ac与相关Makefile.am把新用例纳入构建系统创建/修改.runrunfile编写实际测试脚本.ksh运行测试用例。下面逐一步骤展开。步骤 1配置免密 sudo测试脚本不能以 root 直接运行见第三节的硬性校验因此需要为执行测试的普通用户配置无密码 sudo 权限。步骤 2修改构建系统文件在仓库根目录的configure.ac中于AC_CONFIG_FILES段加入新目录的 Makefiletests/zfs-tests/tests/functional/cli_root/zpool_example/Makefile同时修改 runfiles 的构建清单仓库中对应的构建组织文件为 tests/Makefile.am测试目录的构建入口为 tests/zfs-tests/Makefile.am 与 tests/zfs-tests/tests/Makefile.am它们共同构成套件根 → runfiles → 功能目录的层次化 Makefile 结构将新 runfile 加入分发列表例如pkgdatadir $(datadir)/PACKAGE/runfiles dist_pkgdata_DATA \ zpool_example.run \ common.run \ freebsd.run \ linux.run \ longevity.run \ perf-regression.run \ sanity.run \ sunos.run步骤 3创建 runfile创建tests/runfiles/zpool_example.run定义最常见的运行属性超时、输出目录、tags、用例列表[DEFAULT] timeout 600 outputdir /var/tmp/test_results tags [functional] tests [zpool_example_001_pos]如果是在已有套件中新增用例runfile 已存在只需更新tests 一节。例如新增zpool_example_002_pos时[DEFAULT] timeout 600 outputdir /var/tmp/test_results tags [functional] tests [zpool_example_001_pos, zpool_example_002_pos]步骤 4编写测试脚本在tests/zfs-tests/tests/functional/cli_root/Makefile.am的SUBDIRS下追加目录名注意行尾转义其后还有别的目录zpool_example \然后创建tests/zfs-tests/tests/functional/cli_root/zpool_example/Makefile.am声明该目录下有一个测试脚本zpool_example_001_pos.kshpkgdatadir $(datadir)/PACKAGE/zfs-tests/tests/functional/cli_root/zpool_example dist_pkgdata_SCRIPTS \ zpool_example_001_pos.ksh最后在tests/zfs-tests/tests/functional/cli_root/zpool_example/下创建测试脚本本体# DESCRIPTION: # zpool_example Test # # STRATEGY: # 1. Demo a very basic test case # DISKS_DEV1/dev/loop0 DISKS_DEV2/dev/loop1 TESTPOOLEXAMPLE_POOL function cleanup { # Cleanup destroy_pool $TESTPOOL log_must rm -f $DISKS_DEV1 log_must rm -f $DISKS_DEV2 } log_assert zpool_example # Run function cleanup on exit log_onexit cleanup # Prep backend device log_must dd if/dev/zero of$DISKS_DEV1 bs512 count140000 log_must dd if/dev/zero of$DISKS_DEV2 bs512 count140000 # Create pool log_must zpool create $TESTPOOL $type $DISKS_DEV1 $DISKS_DEV2 log_pass zpool_example这个脚本展示了测试用例的标准骨架与辅助函数用法log_assert声明断言、log_onexit cleanup注册退出清理、log_must包装每条必须成功的命令、log_pass标记通过。这些辅助函数来自测试套件的 include 库仓库内 tests/zfs-tests/include 与 test-runner 的 tests/test-runner/include/logapi.shlib。步骤 5运行测试用例运行方式与第四节一致两种路径皆可通过test-runner.py以 runfile 为输入即执行上面创建的zpool_example.run通过zfs-tests.sh可以执行 runfile也可以用-t直接运行单个用例$ ./scripts/zfs-tests.sh -t tests/functional/cli_root/zpool_example/zpool_example_001_pos.ksh八、编写测试用例的实用建议复用现有库函数绝大多数用例都应基于log_must、log_assert、log_pass、log_onexit等断言/日志原语编写保证结果能被 test-runner 正确归类和汇总善用 tags 与 runfile 分层新用例通常先打上functional标签若运行只需几秒钟可参照 tests/runfiles/common.run 头部的注释建议同时加入sanity.run纳入快速冒烟集环境隔离测试会创建/销毁池与用户务必在专用测试机或 VM 中运行KEEP变量与-x清理选项是保护既有环境的两道防线调试利器失败后使用-k保留现场、-v查看完整环境配置、-t单跑复现、-O/-K详见选项表在超时或挂起时向/dev/kmsg输出调试信息。通过本文介绍的构建、运行、筛选、解读与扩展全流程你可以把 OpenZFS 的上千个功能测试变成自己开发与排障的常备工具也能以zpool_example为模板向社区贡献高质量的测试用例。赞分享操作系统【免费下载链接】zfsOpenZFS on Linux and FreeBSD项目地址https://gitcode.com/gh_mirrors/zf/zfs点击查看免费下载相关推荐curl 测试套件Test Suite完全指南运行、调试与编写测试用例curl 测试套件Test Suite完全指南运行、调试与编写测试用例 本文围绕 curl 仓库中的测试套件展开系统讲解如何从零构建并运行 curl 的CLI网络通信radare2 基于 libFuzzer 的模糊测试实践构建、运行与自定义 Fuzz Target 完全指南radare2 基于 libFuzzer 的模糊测试实践构建、运行与自定义 Fuzz Target 完全指南 导读 本文面向想要为 radare2 https逆向工程网络安全mypy 单元测试实战指南数据驱动 check-*.test 用例编写、测试运行与调试全解mypy 单元测试实战指南数据驱动 check .test 用例编写、测试运行与调试全解 本文是 mypy 仓库单元测试体系的实操指南以 test data开发工具静态分析代码质量创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表