#!/bin/sh set -eu : "${PRE15_DUT:?PRE15_DUT is required}" : "${PRE15_ROOT:?PRE15_ROOT is required}" : "${PRE15_CASE_TMP:?PRE15_CASE_TMP is required}" : "${PRE15_RUN_DIR:?PRE15_RUN_DIR is required}" : "${PRE15_LIB_DIR:?PRE15_LIB_DIR is required}" . "$PRE15_LIB_DIR/runner.sh" fixture_dir=$PRE15_DUT/tests/pre15/fixtures spec=$fixture_dir/B19b-xattr-spec.json generator=$fixture_dir/B19b-xattr-generate.py oracle=$fixture_dir/B19b-xattr-oracle.py probe=$fixture_dir/B19b-xattr-probe.c kld_builder=$fixture_dir/B19b-build-kld.sh gate_script=$PRE15_DUT/tests/pre15/gates/P15-021.sh gate_input=$PRE15_DUT/tests/pre15/gates/P15-021-input.json gate_commit=675ed9b650b3bc157b38bcc165a0cb215a2aa989 gate_base=666e52f710363df07f7c93919eb835d41092d011 artifacts=$PRE15_RUN_DIR/artifacts first=$PRE15_CASE_TMP/first second=$PRE15_CASE_TMP/second gate_clone=$PRE15_CASE_TMP/gate-clone gate_output=$PRE15_CASE_TMP/gate-output for tool in cmp fsck.erofs git mkfs.erofs python3 sha256sum timeout; do command -v "$tool" >/dev/null 2>&1 || \ pre15_infra_blocked "missing B19b host tool: $tool" done pre15_record_fixture b19b-spec "$spec" pre15_record_fixture b19b-generator "$generator" pre15_record_fixture b19b-oracle "$oracle" pre15_record_fixture b19b-probe "$probe" pre15_record_fixture b19b-kld-builder "$kld_builder" pre15_record_fixture b19b-case "$PRE15_DUT/tests/pre15/cases/B19b-xattr-bloom.sh" pre15_record_fixture b19b-gate "$gate_script" pre15_record_fixture b19b-gate-input "$gate_input" pre15_record_fixture b19b-erofs-fs "$PRE15_DUT/src/erofs_fs.h" pre15_record_fixture b19b-internal "$PRE15_DUT/src/internal.h" pre15_record_fixture b19b-xattr "$PRE15_DUT/src/xattr.c" pre15_record_fixture b19b-linux-erofs-fs "$PRE15_ROOT/src-linux/erofs_fs.h" pre15_record_fixture b19b-linux-xattr "$PRE15_ROOT/src-linux/xattr.c" mkdir -p "$artifacts" if ! git clone -q --shared --no-checkout "$PRE15_ROOT" "$gate_clone" \ >"$artifacts/gate-clone.stdout" 2>"$artifacts/gate-clone.stderr" || \ ! git -C "$gate_clone" checkout -q --detach "$gate_commit" \ >"$artifacts/gate-checkout.stdout" 2>"$artifacts/gate-checkout.stderr"; then pre15_runner_fail 'could not materialize the committed P15-021 gate' fi frozen_gate=$gate_clone/repo-pre-15/tests/pre15/gates/P15-021.sh if ! timeout -k 10 240 "$frozen_gate" --base "$gate_base" \ --output "$gate_output" >"$artifacts/gate.stdout" \ 2>"$artifacts/gate.stderr"; then pre15_runner_fail 'committed P15-021 gate did not replay GO' fi if ! python3 -B "$generator" generate --spec "$spec" --output "$first" \ --work "$PRE15_CASE_TMP/first-work" >"$artifacts/generate-first.stdout" \ 2>"$artifacts/generate-first.stderr"; then pre15_runner_fail 'B19b first real-fixture generation failed' fi if ! python3 -B "$generator" generate --spec "$spec" --output "$second" \ --work "$PRE15_CASE_TMP/second-work" >"$artifacts/generate-second.stdout" \ 2>"$artifacts/generate-second.stderr"; then pre15_runner_fail 'B19b repeat real-fixture generation failed' fi if ! cmp "$first/SHA256SUMS" "$second/SHA256SUMS" || \ ! cmp "$first/manifest.json" "$second/manifest.json"; then pre15_runner_fail 'B19b fixture generation is not byte reproducible' fi for image in valid.erofs unknown-filter.erofs feature-off.erofs \ corrupt-shared-count.erofs corrupt-shared-id.erofs; do if ! cmp "$first/$image" "$second/$image"; then pre15_runner_fail "B19b repeat image differs: $image" fi pre15_record_fixture "b19b-$image" "$first/$image" done if ! python3 -B "$oracle" --spec "$spec" --fixtures "$first" \ --root "$PRE15_ROOT" --dut "$PRE15_DUT" \ --report "$artifacts/B19b-oracle.json" \ >"$artifacts/oracle.stdout" 2>"$artifacts/oracle.stderr"; then pre15_dut_fail 'B19b fixture/source/Linux oracle failed' fi cp "$gate_output/result.json" "$artifacts/P15-021-gate-result.json" cp "$gate_output/million.json" "$artifacts/P15-021-million.json" cp "$gate_output/benchmark.json" "$artifacts/P15-021-benchmark.json" cp "$first/SHA256SUMS" "$artifacts/B19b-SHA256SUMS" pre15_record_fixture b19b-generated-sums "$artifacts/B19b-SHA256SUMS" pre15_target_reached if test "${PRE15_MODE:-host}" != qemu; then printf '%s\n' \ 'TC169 host real fixture/hash/filter/integrity/concurrency oracle PASS' \ 'QEMU runtime NOT_RUN in host mode' exit 0 fi for tool in awk clang file nm scp tar; do command -v "$tool" >/dev/null 2>&1 || \ pre15_infra_blocked "missing B19b QEMU tool: $tool" done : "${PRE15_QEMU_CONTROL_PATH:?QEMU control path is required}" : "${PRE15_QEMU_SSH_KEY:?QEMU SSH key is required}" : "${PRE15_QEMU_SSH_PORT:?QEMU SSH port is required}" : "${PRE15_QEMU_SSH_USER:?QEMU SSH user is required}" fixture_archive=$PRE15_CASE_TMP/B19b-fixtures.tar.gz module=$PRE15_CASE_TMP/B19b-erofs.ko if ! /bin/sh "$kld_builder" "$PRE15_DUT" "$PRE15_FREEBSD_SRC" "$module" \ "$PRE15_CASE_TMP/kld-work" >"$artifacts/B19b-kld-build.stdout" \ 2>"$artifacts/B19b-kld-build.stderr"; then pre15_dut_fail 'B19b cross-target KLD build failed' fi pre15_record_module "$module" file "$module" >"$artifacts/B19b-kld-file.txt" sha256sum "$module" >"$artifacts/B19b-kld-sha256.txt" nm -u "$module" | LC_ALL=C sort >"$artifacts/B19b-kld-nm-u.txt" tar -C "$first" -czf "$fixture_archive" . pre15_scp() { timeout -k 5 "${PRE15_GUEST_COMMAND_TIMEOUT:-60}" scp -O -q \ -o BatchMode=yes -o StrictHostKeyChecking=no \ -o UserKnownHostsFile=/dev/null -o ConnectTimeout=5 \ -o "ControlPath=$PRE15_QEMU_CONTROL_PATH" \ -i "$PRE15_QEMU_SSH_KEY" -P "$PRE15_QEMU_SSH_PORT" \ "$1" "$PRE15_QEMU_SSH_USER@127.0.0.1:$2" } if ! pre15_scp "$fixture_archive" /root/B19b-fixtures.tar.gz || \ ! pre15_scp "$probe" /root/B19b-xattr-probe.c || \ ! pre15_scp "$module" /root/B19b-erofs.ko; then pre15_infra_blocked 'could not transfer B19b module, probe, or fixtures' fi if ! pre15_guest_ssh_bounded \ 'rm -rf /root/pre15-b19b-fixtures && mkdir /root/pre15-b19b-fixtures && tar -xzf /root/B19b-fixtures.tar.gz -C /root/pre15-b19b-fixtures'; then pre15_infra_blocked 'could not prepare B19b guest fixtures' fi if pre15_guest_ssh_bounded kldstat -n erofs >/dev/null 2>&1; then pre15_infra_blocked 'FreeBSD guest already has an EROFS module loaded' fi if ! pre15_guest_ssh_bounded kldload /root/B19b-erofs.ko \ >"$artifacts/B19b-kldload.stdout" 2>"$artifacts/B19b-kldload.stderr"; then if grep -q 'module already loaded or in kernel' "$artifacts/B19b-kldload.stderr"; then pre15_infra_blocked 'guest kernel already owns the erofs.1 interface' fi pre15_dut_fail 'B19b exact-source KLD failed to load' fi pre15_own_guest_kld erofs 'B19b exact-source KLD' if ! pre15_guest_ssh_bounded cc -std=c11 -Wall -Wextra -Werror \ -o /root/B19b-xattr-probe /root/B19b-xattr-probe.c; then pre15_infra_blocked 'could not compile the B19b guest probe' fi pre15_mount_image() { pre15_image=$1 pre15_mountpoint=$2 pre15_label=$3 pre15_md=$(pre15_guest_ssh_bounded mdconfig -a -t vnode \ -f "/root/pre15-b19b-fixtures/$pre15_image") || \ pre15_dut_fail "could not attach B19b provider: $pre15_image" case "$pre15_md" in md[0-9]*) ;; *) pre15_runner_fail "unexpected mdconfig output: $pre15_md" ;; esac pre15_own_guest_md "$pre15_md" "$pre15_label provider" pre15_guest_ssh_bounded mkdir -p "$pre15_mountpoint" if ! pre15_guest_ssh_bounded mount -t erofs -o ro "/dev/$pre15_md" \ "$pre15_mountpoint"; then pre15_dut_fail "$pre15_label mount failed" fi pre15_own_guest_mount "$pre15_mountpoint" "$pre15_label mount" } pre15_mount_image valid.erofs /mnt/pre15-b19b-valid 'B19b valid' valid=/mnt/pre15-b19b-valid/target.bin pre15_guest_ssh_bounded /root/B19b-xattr-probe hit "$valid" attr00 0 pre15_guest_ssh_bounded /root/B19b-xattr-probe errno "$valid" user \ absent-00001 87 pre15_guest_ssh_bounded /root/B19b-xattr-probe errno "$valid" user \ absent-00000 87 pre15_guest_ssh_bounded /root/B19b-xattr-probe list "$valid" pre15_guest_ssh_bounded /root/B19b-xattr-probe concurrent "$valid" attr00 \ absent-00001 absent-00000 64 10 pre15_mount_image unknown-filter.erofs /mnt/pre15-b19b-unknown \ 'B19b unknown filter' unknown=/mnt/pre15-b19b-unknown/target.bin pre15_guest_ssh_bounded /root/B19b-xattr-probe hit "$unknown" attr00 0 pre15_guest_ssh_bounded /root/B19b-xattr-probe errno "$unknown" user \ absent-00001 87 pre15_mount_image feature-off.erofs /mnt/pre15-b19b-feature-off \ 'B19b feature off' feature_off=/mnt/pre15-b19b-feature-off/target.bin pre15_guest_ssh_bounded /root/B19b-xattr-probe hit "$feature_off" attr00 0 pre15_guest_ssh_bounded /root/B19b-xattr-probe errno "$feature_off" user \ absent-00001 87 pre15_mount_image corrupt-shared-count.erofs /mnt/pre15-b19b-bad-count \ 'B19b corrupt shared count' pre15_guest_ssh_bounded /root/B19b-xattr-probe errno \ /mnt/pre15-b19b-bad-count/target.bin user absent-00001 97 pre15_mount_image corrupt-shared-id.erofs /mnt/pre15-b19b-bad-id \ 'B19b corrupt shared ID' pre15_guest_ssh_bounded /root/B19b-xattr-probe errno \ /mnt/pre15-b19b-bad-id/target.bin user attr00 97 pre15_guest_ssh_bounded dmesg >"$artifacts/B19b-dmesg.txt" if grep -Eq 'panic:|Fatal trap|lock order reversal|KDB: stack backtrace' \ "$artifacts/B19b-dmesg.txt"; then pre15_dut_fail 'B19b runtime produced a kernel diagnostic' fi printf '%s\n' 'TC169 QEMU hit/miss/collision/fallback/integrity/concurrency PASS'