loggerd 测试:合成 VisionIPC、qlog 抽样与隐私门

作者:

在

结论:loggerd 的测试用合成输入覆盖记录器主链,而不是真实相机链路:它自建名为 camerad 的 VisionIPC server,三路各 40 个 320×240 NV12 缓冲,以 20 Hz 等价循环发送,并随机发布 cereal 服务消息。这决定了它的证据边界——它能校验 rlog/qlog 数量与顺序、段文件集合与书签保留,却不能证明真实相机时序、AV 同步、失帧恢复或编码器 buffer 所有权。另外两处易被高估的断言是:test_rlog 没有在循环后断言发送列表已空,test_record_audio 的 ffprobe 未检查退出码。

输入夹具:合成 VisionIPC 与随机 cereal 服务

CEREAL_SERVICES 取 Event schema 中同时位于服务表、允许记录且名称不含 encode 的主题。_publish_random_messages() 启动 loggerd,对每个服务等读者;每轮给所有服务发新 Event,随机发 200~1000 轮,每 100 轮及结束时等读者更新,随后停止进程。源文档提醒,这个等待反映消息队列读者进度,不等同于磁盘同步完成。

_publish_camera_and_audio_messages() 自建 VisionIPC server,三路各 40 个 320×240 NV12 缓冲;设置 LOGGERD_TEST 与段长,启动 loggerd、encoderd 后以 20 Hz 等价循环编号发送三路缓冲/CameraState、每轮 800 个 int16 零音频样本。它不启动真实 camerad,不测传感器寄存器、曝光、DMA 或时钟同步。源文档也说明该测试文件既有可在 PC 上运行的逻辑,也会调用本机编译产物、FFmpeg、VisionIPC 与日志文件。

源文档特别指出:视频载荷来自 np.empty,未显式初始化为有意义像素;VisionIpcServer.send() 的时间戳参数是 uint64_t,夹具传入 n/fps 浮点秒值,因此不能把测试输出当真实纳秒级相机时间契约。

夹具/检查 实际内容
_get_latest_log_dir() 按目录 mtime 取最新日志段;依赖当前测试 Prefix/LOG_ROOT 下的目录列表。
_gen_bootlog() 调本地 ./bootlog 二进制并在 5 秒 Timeout 内从输出解析文件路径;要求构建产物。
_check_init_data() 只检查第一条消息类型为 initData;没有检查所有字段。
_check_sentinel() 用第二条及末条消息核对 route/segment 起止标记。

各测试的证据范围

测试 断言与限制
test_init_data_values() 写入构建身份等 Params,检查 initData 映射、版本、内核字段;AccessToken 虽在参数列表中但记录值必须为空;只覆盖该组参数,不证明其他敏感字段已净化。
test_bootlog() 写 /tmp/launch_log,要求 bootlog 含两条消息、wall time 约 5 秒内、launchLog 相等;两次 bootlog 的 UID 不同且 BootCount 从 0 到 1;写入的 /tmp/launch_log 未在测试中删除。
test_qlog() 从有/无 decimation 的服务各随机挑子集,只核对 qlog 中每主题的数量是否符合公式;不核对选中消息具体载荷或跨段抽样相位。
test_rlog() 随机 5~10 种服务,逐条从相应服务的发送列表头部弹出并比较序列化字节;没有在循环后断言各发送列表已空。
test_rotation() 随机 2~3 段、4~5 秒/段,要求每段文件名集合恰为 rlog、qlog、qcamera、三路 HEVC;不读取这六个文件的码流或每段内容。
书签保留两组用例 对有/无 userBookmark 的段核对 xattr;不验证跨进程 xattr 负缓存、上传/删除器的后续保留决策。
test_record_front() 真/假两种启动前 Params 值,仅比较最新段 dcamera.hevc 是否存在;不核对动态切换、内容、索引或隐私擦除。
test_record_audio() 真/假两种启动前 Params 值,检查 qcamera 是否有音轨及 rlog 是否出现原始音频;ffprobe 子进程未检查退出码。

test_qlog/test_rlog 使用随机服务及消息数量且未固定 seed,所以一次通过不能覆盖所有主题/抽样组合。源文档也澄清:test_rlog 的逐条比较确实检查了已读取消息的载荷,不应把缺少尾部断言误写成完全没有内容校验。

test_rotation() 只要求每段文件名集合恰为六个文件,不读取码流内容,因此它验证的是段切分与命名,而不是每段编码的正确性。

隐私与录音门的边界

test_init_data_values() 只覆盖该组参数,源文档明确不证明其他敏感字段已净化。test_record_front() 只比较最新段 dcamera.hevc 是否存在。test_record_audio() 存在一个易漏点:subprocess.run(ffprobe..., capture_output=True) 未检查退出码,命令失败而 stdout 为空时,关闭录音用例的「无音轨」条件仍可能通过。源文档据此要求在插件化时区分「明确无音轨」和「探针失败」。

书签保留的两组用例只核对 xattr,源文档指出它们不验证跨进程 xattr 负缓存、上传/删除器的后续保留决策;test_bootlog() 写入的 /tmp/launch_log 也未在测试中删除。这些残留与边界提醒说明,测试覆盖的是「可见输入 + 源码断言」,不是端到端的保留与清理保证。

插件化验证要求

将记录功能拆成插件时,应保留独立契约:服务注册/抽样、rlog 顺序和完整性、媒体包/索引对应、音频/座舱录制许可、书签后的保留与上传、异常关机后的文件可读性。对每个测试输入记录种子,断言发送与接收双向数量相等;FFprobe 等外部探针须检查退出码。

真实相机插件还需带纳秒时间戳的帧级对齐、NV12 形状/stride/有效位、坏帧与断流注入。源文档最后限定:全部结论限定于源码断言与可见输入,未运行构建、FFmpeg、进程或媒体生成,因此无法确认各测试在本归档环境的实际通过情况,本 suite 也不能替代实机时序和隐私审计。

常见问题

loggerd 测试用的是真实相机吗?

不是。源文档明确夹具自建名为 camerad 的 VisionIPC server,三路各 40 个 320×240 NV12 缓冲,不启动真实 camerad,也不测传感器寄存器、曝光、DMA 或时钟同步。

为什么测试里的相机时间戳不能当真实契约?

VisionIpcServer.send() 的时间戳参数是 uint64_t,而夹具传入 n/fps 浮点秒值,源文档明确不能把测试输出当真实纳秒级相机时间契约,具体转换效果需用构建后的绑定验证。

test_rlog 通过是否说明日志完整?

不足以保证完整。它逐条比较从各服务发送列表头部弹出的序列化字节,但没有在循环后断言发送列表已空,因此若日志只保留每主题的正确前缀,尾部缺失不会由这条断言本身发现。

test_record_audio 判定「无音轨」可信吗?

需要警惕。源文档指出 subprocess.run(ffprobe..., capture_output=True) 未检查退出码,命令失败而 stdout 为空时,关闭录音用例的「无音轨」条件仍可能通过,插件化时应区分「明确无音轨」和「探针失败」。

延伸阅读

参考资料

  • 项目 02 —— openpilot-research/LOGGERD_TEST_SYNTHETIC_VIPC_QLOG_RLOG_PRIVACY_GATES_DEEP_DIVE.md(取用了合成 VisionIPC 与随机 cereal 夹具、各测试证据范围表、隐私与录音门边界、插件化验证要求)。

说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。

更新记录

首次发布 2026-10-11 最近核对:2026-10-11

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注