# repo22 手工基础测试报告

- 执行时间：2026-08-08 11:38-11:43 UTC
- 工作区：`/work`
- repo22：`/work/repo-community/repo22`
- Git 分支：`main`
- 测试源码提交：`0c173fa5c07a0c2af7dafcf8f89f0167ae3e1f9d`
- FreeBSD VM：SSH `127.0.0.1:9222`
- 执行方式：手工构建、SSH/SCP 和逐条 shell 命令；未生成测试 wrapper 或 CI；未修改源码
- 前一轮失败报告：保留 `tests/results/manual/2026-08-08T1114Z/manual-test-report.md`
- 总体结论：**TC001 PASS；TC009 FAIL（用例中的 GNU 风格 `stat` 命令与 FreeBSD `stat(1)` 不兼容）**

## 结果摘要

| 项目 | 状态 | 实际结果 |
|---|---|---|
| repo22 模块重建 | PASS | `build/erofs.ko`，41712 字节 |
| `bcmp` 构建检查 | PASS | `nm -u` 中没有 `bcmp` |
| 模块传输完整性 | PASS | host/guest SHA-256 均为 `6c13819ee36b1f7fe62ea084640fdefb2e871f245462291ce4c18f1ee93a684f` |
| `kldload` / `kldstat` / `kldunload` | PASS | canonical `/root/erofs.ko` 三步退出码均为 0 |
| 固定 plain 镜像 | PASS | 10 MiB、2560×4096 blocks、重复构建逐字节相同 |
| TC001-mount-basic | **PASS** | 挂载、只读标志、容量、读取、卸载均符合预期 |
| TC009-statfs-basic | **FAIL** | `df`/只读/容量正确；原文步骤 3 未显示文件系统信息，步骤 4 返回 1 |
| 清理 | PASS | 无 EROFS 模块、挂载和 md 设备残留；guest 临时文件已删除 |

## 1. Host 环境与源码状态

实际命令：

```sh
date -u '+%Y-%m-%dT%H:%M:%SZ'
uname -a
cat /etc/os-release
git rev-parse HEAD
git branch --show-current
git show HEAD:repo-community/repo22/build.sh | sha256sum
sha256sum repo-community/repo22/build.sh
git diff -- repo-community/repo22/src repo-community/repo22/build.sh
```

实际输出：

```text
2026-08-08T11:38:49Z
Linux da8f2da26d77 6.12.74+deb13+1-cloud-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.74-2 (2026-03-08) x86_64 GNU/Linux
PRETTY_NAME="Debian GNU/Linux 13 (trixie)"
VERSION_ID="13"
DEBIAN_VERSION_FULL=13.5
0c173fa5c07a0c2af7dafcf8f89f0167ae3e1f9d
main
70b6c015b33479c271e11abf36108c7f9e7ca9e2b9aa9d931fe7ae21f27f59ff  -
70b6c015b33479c271e11abf36108c7f9e7ca9e2b9aa9d931fe7ae21f27f59ff  repo-community/repo22/build.sh
<git diff 无输出>
```

## 2. 重新构建模块与 `bcmp` 检查

实际命令：

```sh
cd /work/repo-community/repo22
FREEBSD_SRC=/work/dev-freebsd-releng ./build.sh
ls -l --full-time build/erofs.ko
sha256sum build/erofs.ko
nm -u build/erofs.ko | awk '$NF == "bcmp" {print; found=1} END {if (!found) print "none"}'
```

实际输出：

```text
==> Building repo22 erofs.ko
/work/repo-community/repo22/src/lzma.c:133:19: warning: result of comparison of constant 256 with expression of type 'uint8_t' (aka 'unsigned char') is always true [-Wtautological-constant-out-of-range-compare]
  133 |                                 } while (byte < 0x100);
      |                                          ~~~~ ^ ~~~~~
/work/repo-community/repo22/src/lzma.c:135:16: warning: result of comparison of constant 256 with expression of type 'uint8_t' (aka 'unsigned char') is always true [-Wtautological-constant-out-of-range-compare]
  135 |                         while (byte < 0x100)
      |                                ~~~~ ^ ~~~~~
2 warnings generated.
==> SUCCESS: /work/repo-community/repo22/build/erofs.ko
-rw-r--r-- 1 root root 41712 2026-08-08 11:38:52.056076393 +0000 build/erofs.ko
6c13819ee36b1f7fe62ea084640fdefb2e871f245462291ce4c18f1ee93a684f  build/erofs.ko
none
```

结论：构建退出 0，上一轮导致 guest 加载失败的未解析 `bcmp` 已不在模块中。

## 3. SSH 与 Guest 基线

普通公钥探测：

```sh
timeout 5 bash -c '</dev/tcp/127.0.0.1/9222'
ssh -o BatchMode=yes -o StrictHostKeyChecking=no \
  -o UserKnownHostsFile=/dev/null -o ConnectTimeout=5 \
  -p 9222 root@127.0.0.1 'date -u; uname -a; id; kldstat'
```

```text
PORT_OPEN
root@127.0.0.1: Permission denied (publickey,keyboard-interactive).
```

按现有 VM helper 的固定密码认证方式继续。密码脱敏；临时 askpass 文件位于 `/tmp`，不是测试 wrapper，未加入仓库。

```sh
cat > /tmp/repo22-ssh-askpass.sh <<'ASKPASS'
#!/bin/sh
printf '%s\n' "$REPO22_VM_PASS"
ASKPASS
chmod 700 /tmp/repo22-ssh-askpass.sh
export REPO22_VM_PASS='<redacted>'
export DISPLAY=:0 SSH_ASKPASS=/tmp/repo22-ssh-askpass.sh SSH_ASKPASS_REQUIRE=force
setsid -w ssh \
  -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
  -o PreferredAuthentications=keyboard-interactive,password \
  -o PubkeyAuthentication=no -p 9222 root@127.0.0.1 '
date -u "+%Y-%m-%dT%H:%M:%SZ"
uname -a
freebsd-version -ku
id
sysctl kern.securelevel
command -v kldload; command -v kldstat; command -v kldunload
command -v mdconfig; command -v mount; command -v umount
command -v stat; command -v sha256
kldstat | grep -i erofs; echo "kldstat_erofs_exit=$?"
mount | grep -i erofs; echo "mount_erofs_exit=$?"
mdconfig -l
'
```

```text
2026-08-08T11:39:48Z
FreeBSD freebsd-build 15.0-RELEASE-p8 FreeBSD 15.0-RELEASE-p8 releng/15.0-n281036-53054229dcb3 GENERIC amd64
15.0-RELEASE-p8
15.0-RELEASE-p8
uid=0(root) gid=0(wheel) groups=0(wheel),5(operator)
kern.securelevel: -1
/sbin/kldload
/sbin/kldstat
/sbin/kldunload
/sbin/mdconfig
/sbin/mount
/sbin/umount
/usr/bin/stat
/sbin/sha256
kldstat_erofs_exit=1
mount_erofs_exit=1
<mdconfig -l 无输出>
```

结论：VM 是 FreeBSD 15.0-RELEASE-p8 amd64；初始无 EROFS 模块、挂载或 md 设备。

## 4. 模块复制与生命周期回归

```sh
setsid -w scp -O \
  -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
  -o PreferredAuthentications=keyboard-interactive,password \
  -o PubkeyAuthentication=no -P 9222 \
  repo-community/repo22/build/erofs.ko \
  root@127.0.0.1:/root/repo22-erofs.ko
```

首次使用非 canonical 文件名加载的实际命令与输出：

```sh
ls -l /root/repo22-erofs.ko
sha256 /root/repo22-erofs.ko
dmesg | grep -E "bcmp|repo22-erofs|linker_load_file|erofs" | tail -20
kldload /root/repo22-erofs.ko; echo "kldload_exit=$?"
kldstat | grep -i erofs; echo "kldstat_grep_exit=$?"
dmesg | grep -E "bcmp|repo22-erofs|linker_load_file|erofs" | tail -20
kldunload erofs; echo "kldunload_exit=$?"
```

```text
-rw-r--r--  1 root wheel 41712 Aug  8 11:40 /root/repo22-erofs.ko
SHA256 (/root/repo22-erofs.ko) = 6c13819ee36b1f7fe62ea084640fdefb2e871f245462291ce4c18f1ee93a684f
link_elf_obj: symbol bcmp undefined
linker_load_file: /root/repo22-erofs.ko - unsupported file type
kldload_exit=0
 5    1 0xffffffff82822000     5d30 repo22-erofs.ko
kldstat_grep_exit=0
link_elf_obj: symbol bcmp undefined
linker_load_file: /root/repo22-erofs.ko - unsupported file type
kldunload: can't find file erofs
kldunload_exit=1
```

两条 `bcmp`/`unsupported file type` 是本轮加载前已存在的上一轮 dmesg 历史行；加载前后输出相同，本轮 `kldload_exit=0`，没有新增链接错误。首次卸载失败仅因加载文件名是 `repo22-erofs.ko`。

按模块 ID 清理后，用 canonical 文件名重新执行完整生命周期：

```sh
module_id=$(kldstat | awk '/repo22-erofs[.]ko/ {print $1}')
echo "module_id=$module_id"
kldunload -i "$module_id"; echo "kldunload_by_id_exit=$?"
kldstat | grep -i erofs; echo "post_id_unload_kldstat_exit=$?"
cp -f /root/repo22-erofs.ko /root/erofs.ko
sha256 /root/erofs.ko
kldload /root/erofs.ko; echo "kldload_exit=$?"
kldstat | grep -i erofs; echo "kldstat_grep_exit=$?"
kldunload erofs; echo "kldunload_exit=$?"
kldstat | grep -i erofs; echo "post_unload_kldstat_grep_exit=$?"
```

```text
module_id=5
kldunload_by_id_exit=0
post_id_unload_kldstat_exit=1
SHA256 (/root/erofs.ko) = 6c13819ee36b1f7fe62ea084640fdefb2e871f245462291ce4c18f1ee93a684f
kldload_exit=0
 5    1 0xffffffff82822000     5d30 erofs.ko
kldstat_grep_exit=0
kldunload_exit=0
post_unload_kldstat_grep_exit=1
```

结论：`bcmp` 修复后的 `kldload`、`kldstat`、`kldunload` 回归 **PASS**。

## 5. 固定 plain 镜像

工具检查：

```sh
command -v mkfs.erofs
mkfs.erofs -V
command -v dump.erofs
dump.erofs -V
```

```text
/usr/bin/mkfs.erofs
mkfs.erofs (erofs-utils) 1.8.6
available compressors: lz4, lz4hc, lzma, deflate, libdeflate, zstd
/usr/bin/dump.erofs
dump.erofs (erofs-utils) 1.8.6
```

首次尝试显式禁用 inline：

```sh
mkfs.erofs -b4096 -x-1 -T0 --all-root --ignore-mtime \
  -Enoinline -L repo22-manual \
  /tmp/repo22-manual-plain/test.erofs \
  /tmp/repo22-manual-plain/src
```

```text
<E> erofs: unknown extended option noinline
Try 'mkfs.erofs --help' for more information.
mkfs.erofs 1.8.6
```

该命令退出 1 且未产出镜像。随后用整块大小、无压缩的主文件，并固定时间戳、UUID、label、属主和 xattr 设置：

```sh
rm -rf /tmp/repo22-manual-plain
mkdir -p /tmp/repo22-manual-plain/src
printf 'repo22 FreeBSD EROFS manual test\n' > /tmp/repo22-manual-plain/src/README.txt
dd if=/dev/zero of=/tmp/repo22-manual-plain/src/plain.bin bs=4096 count=2559 status=none
touch -d @0 /tmp/repo22-manual-plain/src \
  /tmp/repo22-manual-plain/src/README.txt \
  /tmp/repo22-manual-plain/src/plain.bin
mkfs.erofs -b4096 -x-1 -T0 --all-root --ignore-mtime \
  -U 00000000-0000-0000-0000-000000000022 -L repo22-manual \
  /tmp/repo22-manual-plain/test.erofs /tmp/repo22-manual-plain/src
mkfs.erofs -b4096 -x-1 -T0 --all-root --ignore-mtime \
  -U 00000000-0000-0000-0000-000000000022 -L repo22-manual \
  /tmp/repo22-manual-plain/test-repeat.erofs /tmp/repo22-manual-plain/src
cmp /tmp/repo22-manual-plain/test.erofs /tmp/repo22-manual-plain/test-repeat.erofs
echo "cmp_exit=$?"
sha256sum /tmp/repo22-manual-plain/src/README.txt \
  /tmp/repo22-manual-plain/src/plain.bin \
  /tmp/repo22-manual-plain/test.erofs \
  /tmp/repo22-manual-plain/test-repeat.erofs
dump.erofs -s /tmp/repo22-manual-plain/test.erofs
```

关键实际输出：

```text
Filesystem UUID: 00000000-0000-0000-0000-000000000022
Filesystem total blocks: 2560 (of 4096-byte blocks)
Filesystem total inodes: 3
Filesystem total metadata blocks: 1
cmp_exit=0
c1f6e23b161735085a00a36cb72926bbe187a63eabcb4425a4f5acad5fe3ff4a  /tmp/repo22-manual-plain/src/README.txt
20bf72d8cbc4dbc7e214b671f2547e3e8d57d455d10ac6b645656ef26afc6880  /tmp/repo22-manual-plain/src/plain.bin
fec83f76b8b7eb1d83a9a51246e093c319061838b04633184e9a0c601a386ff3  /tmp/repo22-manual-plain/test.erofs
fec83f76b8b7eb1d83a9a51246e093c319061838b04633184e9a0c601a386ff3  /tmp/repo22-manual-plain/test-repeat.erofs
Filesystem magic number:                      0xE0F5E1E2
Filesystem blocksize:                         4096
Filesystem blocks:                            2560
Filesystem inode count:                       3
Filesystem created:                           Thu Jan  1 00:00:00 1970
Filesystem features:                          sb_csum mtime
Filesystem UUID:                              00000000-0000-0000-0000-000000000022
```

镜像大小为 10485760 字节，即 10 MiB。两次独立输出逐字节相同。

复制并验证：

```sh
setsid -w scp -O <同上 SSH 认证选项> -P 9222 \
  /tmp/repo22-manual-plain/test.erofs root@127.0.0.1:/root/test.erofs
ls -l /root/test.erofs
sha256 /root/test.erofs
```

```text
-rw-r--r--  1 root wheel 10485760 Aug  8 11:42 /root/test.erofs
SHA256 (/root/test.erofs) = fec83f76b8b7eb1d83a9a51246e093c319061838b04633184e9a0c601a386ff3
```

## 6. TC001-mount-basic

原文步骤前仅做规定前置条件：把 canonical 模块放入标准搜索目录，并附加镜像为 `/dev/md0`。

```sh
ls -l /boot/modules/erofs.ko
cp -f /root/erofs.ko /boot/modules/erofs.ko
sha256 /boot/modules/erofs.ko
umount /mnt/test 2>/dev/null
mdconfig -d -u md0 2>/dev/null
mdconfig -a -t vnode -f /root/test.erofs -u 0
echo "mdconfig_attach_exit=$?"
mdconfig -lv
```

```text
ls: /boot/modules/erofs.ko: No such file or directory
SHA256 (/boot/modules/erofs.ko) = 6c13819ee36b1f7fe62ea084640fdefb2e871f245462291ce4c18f1ee93a684f
mdconfig_attach_exit=0
md0    vnode      10M    /root/test.erofs    -
```

原文步骤 1-5：

```sh
kldload erofs; echo "tc001_step1_exit=$?"
kldstat | grep erofs; echo "tc001_step2_pipeline_exit=$?"
mkdir -p /mnt/test; echo "tc001_step3_exit=$?"
mount -t erofs /dev/md0 /mnt/test; echo "tc001_step4_exit=$?"
mount | grep erofs; echo "tc001_step5a_pipeline_exit=$?"
df -h /mnt/test; echo "tc001_step5b_exit=$?"
```

```text
tc001_step1_exit=0
 5    1 0xffffffff82822000     5d30 erofs.ko
tc001_step2_pipeline_exit=0
tc001_step3_exit=0
tc001_step4_exit=0
/dev/md0 on /mnt/test (erofs, local, read-only)
tc001_step5a_pipeline_exit=0
Filesystem    Size    Used   Avail Capacity  Mounted on
/dev/md0       10M     10M      0B   100%    /mnt/test
tc001_step5b_exit=0
```

补充读取验证：

```sh
ls -la /mnt/test
sha256 /mnt/test/README.txt /mnt/test/plain.bin
cat /mnt/test/README.txt
echo "tc001_content_exit=$?"
dmesg | tail -20
```

```text
ls: /mnt/test/.: Operation not supported
ls: /mnt/test/README.txt: Operation not supported
ls: /mnt/test/plain.bin: Operation not supported
total 10248
drwxr-xr-x  2 root wheel       70 Jan  1  1970 .
drwxr-xr-x  3 root wheel      512 Aug  8 11:42 ..
-rw-r--r--  1 root wheel       33 Jan  1  1970 README.txt
-rw-r--r--  1 root wheel 10481664 Jan  1  1970 plain.bin
SHA256 (/mnt/test/README.txt) = c1f6e23b161735085a00a36cb72926bbe187a63eabcb4425a4f5acad5fe3ff4a
SHA256 (/mnt/test/plain.bin) = 20bf72d8cbc4dbc7e214b671f2547e3e8d57d455d10ac6b645656ef26afc6880
repo22 FreeBSD EROFS manual test
tc001_content_exit=0
```

`ls -la` 在读取附加 stat/pathconf 信息时打印 `Operation not supported`，但仍列出目录；两个文件均完整可读且 SHA-256 与 host 一致。该补充现象不属于 TC001 规定判定项，单独保留为观察。`dmesg | tail -20` 没有本轮 mount 错误；末尾两条 `bcmp` 行是上一轮历史记录。

原文步骤 6-7：

```sh
umount /mnt/test; echo "tc001_step6_exit=$?"
mount | grep erofs; echo "tc001_step7_pipeline_exit=$?"
```

```text
tc001_step6_exit=0
<mount | grep erofs 无输出>
tc001_step7_pipeline_exit=1
```

步骤 7 的 grep 返回 1 正是“没有 EROFS 挂载”的预期。

**TC001 最终判定：PASS。**

## 7. TC009-statfs-basic

原文步骤 1-2：

```sh
mount -t erofs /dev/md0 /mnt/test; echo "tc009_step1_exit=$?"
df -h /mnt/test; echo "tc009_step2a_exit=$?"
df -i /mnt/test; echo "tc009_step2b_exit=$?"
```

```text
tc009_step1_exit=0
Filesystem    Size    Used   Avail Capacity  Mounted on
/dev/md0       10M     10M      0B   100%    /mnt/test
tc009_step2a_exit=0
Filesystem 1K-blocks  Used Avail Capacity iused ifree %iused  Mounted on
/dev/md0       10240 10240     0   100%       3     0  100%   /mnt/test
tc009_step2b_exit=0
```

总容量 10 MiB、可用块 0、inode 总数 3、可用 inode 0。

严格执行原文步骤 3：

```sh
stat -f /mnt/test
echo "tc009_step3_exit=$?"
```

```text
/mnt/test
tc009_step3_exit=0
```

FreeBSD `stat(1)` 的 `-f` 表示“后一个参数是格式字符串”，不是 GNU `stat -f` 的“显示文件系统状态”。命令只回显 `/mnt/test`，没有达到用例要求的“Shows EROFS filesystem type”。

严格执行原文步骤 4：

```sh
stat -f -f "%b %f %c %a %d %i %t %n" /mnt/test
echo "tc009_step4_exit=$?"
```

```text
stat: %b %f %c %a %d %i %t %n: No such file or directory
-f
tc009_step4_exit=1
```

原文步骤 5 与补充容量核对：

```sh
mount | grep /mnt/test | grep read-only
echo "tc009_step5_pipeline_exit=$?"
mount | grep /mnt/test
df -k /mnt/test
```

```text
/dev/md0 on /mnt/test (erofs, local, read-only)
tc009_step5_pipeline_exit=0
/dev/md0 on /mnt/test (erofs, local, read-only)
Filesystem 1024-blocks  Used Avail Capacity  Mounted on
/dev/md0         10240 10240     0   100%    /mnt/test
```

`10240` 个 1 KiB 块等于 `2560` 个 4096-byte 块；只读标志、文件系统类型和 free=0 均正确。但严格按用例判定，步骤 3 未产生要求的信息，步骤 4 退出 1。

**TC009 最终判定：FAIL。失败原因是测试文档中的 `stat` 命令与 FreeBSD `stat(1)` CLI 语义不兼容；本轮未修改测试文档或源码。**

## 8. 清理与最终状态

```sh
umount /mnt/test; echo "cleanup_umount_exit=$?"
mdconfig -d -u md0; echo "cleanup_mdconfig_exit=$?"
kldunload erofs; echo "cleanup_kldunload_exit=$?"
rmdir /mnt/test; echo "cleanup_rmdir_exit=$?"
rm -f /boot/modules/erofs.ko /root/test.erofs /root/erofs.ko /root/repo22-erofs.ko
echo "cleanup_rm_exit=$?"
kldstat | grep -i erofs; echo "final_kldstat_grep_exit=$?"
mount | grep -i erofs; echo "final_mount_grep_exit=$?"
mdconfig -l
```

```text
cleanup_umount_exit=0
cleanup_mdconfig_exit=0
cleanup_kldunload_exit=0
cleanup_rmdir_exit=0
cleanup_rm_exit=0
final_kldstat_grep_exit=1
final_mount_grep_exit=1
<mdconfig -l 无输出>
```

结论：guest 清理完成，无模块、挂载、md 设备或本轮临时文件残留。

## 最终判定

- `bcmp` 修复后模块构建与 host 检查：**PASS**
- guest `kldload` / `kldstat` / `kldunload`：**PASS**
- 固定 10 MiB plain 镜像生成、重复性与 SHA-256：**PASS**
- TC001-mount-basic：**PASS**
- TC009-statfs-basic：**FAIL（测试命令不兼容 FreeBSD `stat(1)`）**
- BLOCKED：**0**
- 源码修改：**无**
- wrapper/CI：**未生成**
