199 lines
8.2 KiB
Bash
Executable File
199 lines
8.2 KiB
Bash
Executable File
#!/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_SMOKE_CODEC:?PRE15_SMOKE_CODEC is required}"
|
|
. "$PRE15_LIB_DIR/runner.sh"
|
|
|
|
fixture_dir=$PRE15_DUT/tests/pre15/fixtures
|
|
generator=$fixture_dir/SMOKE-generate.py
|
|
kldsym_probe=$fixture_dir/SMOKE-kldsym.c
|
|
kld_builder=$fixture_dir/B28-build-kld.sh
|
|
artifacts=$PRE15_RUN_DIR/artifacts
|
|
source_first=$PRE15_CASE_TMP/source-first
|
|
source_second=$PRE15_CASE_TMP/source-second
|
|
image=$PRE15_CASE_TMP/SMOKE-$PRE15_SMOKE_CODEC.erofs
|
|
module=$PRE15_CASE_TMP/SMOKE-$PRE15_SMOKE_CODEC-erofs.ko
|
|
|
|
case "$PRE15_SMOKE_CODEC" in
|
|
plain)
|
|
config=0
|
|
uuid=00000000-0000-4000-8000-000000000100
|
|
mkfs_codec=
|
|
case_timeout=180
|
|
;;
|
|
lz4)
|
|
config=0
|
|
uuid=00000000-0000-4000-8000-000000000104
|
|
mkfs_codec='-zlz4 -C4096'
|
|
case_timeout=240
|
|
;;
|
|
lzma)
|
|
config=0
|
|
uuid=00000000-0000-4000-8000-0000000001a0
|
|
mkfs_codec='-zlzma,level=6,dictsize=65536 -C4096'
|
|
case_timeout=300
|
|
;;
|
|
zstd)
|
|
config=1
|
|
uuid=00000000-0000-4000-8000-00000000025d
|
|
mkfs_codec='-zzstd,level=3,dictsize=65536 -C4096'
|
|
case_timeout=300
|
|
;;
|
|
*) pre15_runner_fail "unknown smoke codec: $PRE15_SMOKE_CODEC" ;;
|
|
esac
|
|
|
|
for tool in clang cmp diff file mkfs.erofs nm python3 scp sha256sum timeout; do
|
|
command -v "$tool" >/dev/null 2>&1 || \
|
|
pre15_infra_blocked "missing smoke tool: $tool"
|
|
done
|
|
for fixture in "$generator" "$kldsym_probe" "$kld_builder" \
|
|
"$PRE15_DUT/tests/pre15/cases/SMOKE-common.sh"; do
|
|
pre15_record_fixture "smoke-$(basename "$fixture")" "$fixture"
|
|
done
|
|
mkdir -p "$artifacts"
|
|
if ! python3 -B "$generator" --output "$source_first" \
|
|
>"$artifacts/source-first.json" 2>"$artifacts/source-first.stderr" || \
|
|
! python3 -B "$generator" --output "$source_second" \
|
|
>"$artifacts/source-second.json" 2>"$artifacts/source-second.stderr"; then
|
|
pre15_runner_fail 'smoke fixture generation failed'
|
|
fi
|
|
if ! diff -qr "$source_first" "$source_second" \
|
|
>"$artifacts/source-repeat.diff" || \
|
|
! cmp "$artifacts/source-first.json" "$artifacts/source-second.json"; then
|
|
pre15_runner_fail 'smoke source fixture is not byte reproducible'
|
|
fi
|
|
if ! timeout -k 5 120 sh -c \
|
|
"mkfs.erofs -d0 -T0 --all-time --all-root --workers=1 --sort=path -x-1 -U$uuid $mkfs_codec '$image' '$source_first'" \
|
|
>"$artifacts/mkfs.stdout" 2>"$artifacts/mkfs.stderr"; then
|
|
pre15_runner_fail "$PRE15_SMOKE_CODEC smoke image generation failed"
|
|
fi
|
|
if ! timeout -k 10 600 /bin/sh "$kld_builder" "$PRE15_DUT" \
|
|
"$PRE15_FREEBSD_SRC" "$module" "$PRE15_CASE_TMP/kld-work" "$config" \
|
|
>"$artifacts/kld-build.stdout" 2>"$artifacts/kld-build.stderr"; then
|
|
pre15_dut_fail "$PRE15_SMOKE_CODEC smoke cross-target KLD build failed"
|
|
fi
|
|
pre15_record_module "$module"
|
|
sha256sum "$image" >"$artifacts/image-sha256.txt"
|
|
sha256sum "$module" >"$artifacts/kld-sha256.txt"
|
|
file "$module" >"$artifacts/kld-file.txt"
|
|
nm -u "$module" | LC_ALL=C sort >"$artifacts/kld-nm-u.txt"
|
|
pre15_target_reached
|
|
|
|
test "${PRE15_MODE:-}" = qemu || \
|
|
pre15_runner_fail 'smoke cases require QEMU mode'
|
|
: "${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}"
|
|
|
|
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"
|
|
}
|
|
|
|
remote_root=/root/pre15-smoke-$PRE15_SMOKE_CODEC
|
|
pre15_guest_ssh_bounded rm -rf "$remote_root"
|
|
pre15_guest_ssh_bounded mkdir -p "$remote_root"
|
|
if ! pre15_scp "$image" "$remote_root/image.erofs" || \
|
|
! pre15_scp "$module" "$remote_root/erofs.ko" || \
|
|
! pre15_scp "$kldsym_probe" "$remote_root/SMOKE-kldsym.c"; then
|
|
pre15_infra_blocked "$PRE15_SMOKE_CODEC smoke transfer failed"
|
|
fi
|
|
if test "$PRE15_SMOKE_CODEC" = zstd; then
|
|
if ! pre15_guest_ssh_bounded \
|
|
"cc -O2 -Wall -Wextra -Werror -std=c17 '$remote_root/SMOKE-kldsym.c' -o '$remote_root/SMOKE-kldsym'"; then
|
|
pre15_infra_blocked 'could not compile guest ZSTDIO capability probe'
|
|
fi
|
|
if ! pre15_guest_ssh_bounded "$remote_root/SMOKE-kldsym" \
|
|
ZSTD_DCtx_setParameter ZSTD_createDCtx_advanced \
|
|
ZSTD_decompressStream ZSTD_freeDCtx ZSTD_isError \
|
|
>"$artifacts/zstdio-capability.txt" 2>"$artifacts/zstdio-capability.stderr"; then
|
|
pre15_infra_blocked 'running guest kernel lacks required ZSTDIO symbols'
|
|
fi
|
|
fi
|
|
if pre15_guest_ssh_bounded kldstat -q -m erofs >/dev/null 2>&1; then
|
|
pre15_infra_blocked 'guest kernel already owns the erofs.1 interface'
|
|
fi
|
|
if ! pre15_guest_ssh_bounded kldload "$remote_root/erofs.ko" \
|
|
>"$artifacts/kldload.stdout" 2>"$artifacts/kldload.stderr"; then
|
|
if grep -q 'module already loaded or in kernel' \
|
|
"$artifacts/kldload.stderr"; then
|
|
pre15_infra_blocked 'guest kernel already owns the erofs.1 interface'
|
|
fi
|
|
if test "$PRE15_SMOKE_CODEC" = zstd && \
|
|
grep -Eqi 'link_elf|symbol|not defined' "$artifacts/kldload.stderr"; then
|
|
pre15_infra_blocked 'zstdio1 EROFS KLD cannot load on this guest kernel'
|
|
fi
|
|
pre15_dut_fail "$PRE15_SMOKE_CODEC smoke KLD failed to load"
|
|
fi
|
|
pre15_own_guest_kld erofs "$PRE15_SMOKE_CODEC smoke KLD"
|
|
smoke_md=$(pre15_guest_ssh_bounded mdconfig -a -t vnode \
|
|
-f "$remote_root/image.erofs") || \
|
|
pre15_dut_fail "$PRE15_SMOKE_CODEC smoke md attach failed"
|
|
case "$smoke_md" in
|
|
md[0-9]*) ;;
|
|
*) pre15_runner_fail "unexpected smoke md unit: $smoke_md" ;;
|
|
esac
|
|
pre15_own_guest_md "$smoke_md" "$PRE15_SMOKE_CODEC smoke md"
|
|
smoke_mount=/mnt/pre15-smoke-$PRE15_SMOKE_CODEC
|
|
pre15_guest_ssh_bounded mkdir -p "$smoke_mount"
|
|
if ! pre15_guest_ssh_bounded mount -t erofs -o ro "/dev/$smoke_md" "$smoke_mount"; then
|
|
pre15_dut_fail "$PRE15_SMOKE_CODEC smoke readonly mount failed"
|
|
fi
|
|
pre15_own_guest_mount "$smoke_mount" "$PRE15_SMOKE_CODEC smoke mount"
|
|
|
|
python3 -B - "$artifacts/source-first.json" "$artifacts/expected-files.tsv" <<'PY'
|
|
import json
|
|
from pathlib import Path
|
|
import sys
|
|
|
|
manifest = json.loads(Path(sys.argv[1]).read_text(encoding="ascii"))
|
|
lines = [f"{item['path']}\t{item['size']}\t{item['sha256']}" for item in manifest["files"]]
|
|
Path(sys.argv[2]).write_text("\n".join(lines) + "\n", encoding="ascii")
|
|
PY
|
|
while IFS="$(printf '\t')" read -r path expected_size expected_hash; do
|
|
actual_size=$(pre15_guest_ssh_bounded stat -f %z "$smoke_mount/$path") || \
|
|
pre15_dut_fail "$PRE15_SMOKE_CODEC smoke stat failed: $path"
|
|
actual_hash=$(pre15_guest_ssh_bounded sha256 -q "$smoke_mount/$path") || \
|
|
pre15_dut_fail "$PRE15_SMOKE_CODEC smoke hash failed: $path"
|
|
printf '%s\t%s\t%s\n' "$path" "$actual_size" "$actual_hash" \
|
|
>>"$artifacts/guest-files.tsv"
|
|
test "$actual_size" = "$expected_size" && test "$actual_hash" = "$expected_hash" || \
|
|
pre15_dut_fail "$PRE15_SMOKE_CODEC smoke file mismatch: $path"
|
|
done <"$artifacts/expected-files.tsv"
|
|
pre15_guest_ssh_bounded \
|
|
"find '$smoke_mount' -mindepth 1 -maxdepth 1 -exec basename '{}' ';' | sort" \
|
|
>"$artifacts/guest-root-entries.txt"
|
|
printf '%s\n' empty nested payload.bin >"$artifacts/expected-root-entries.txt"
|
|
cmp "$artifacts/expected-root-entries.txt" "$artifacts/guest-root-entries.txt" || \
|
|
pre15_dut_fail "$PRE15_SMOKE_CODEC smoke root readdir set mismatch"
|
|
|
|
if test "$PRE15_SMOKE_CODEC" = lz4; then
|
|
dd if="$source_first/payload.bin" bs=1 skip=4093 count=131071 2>/dev/null | \
|
|
sha256sum | awk '{print $1}' >"$artifacts/expected-range-sha256.txt"
|
|
pre15_guest_ssh_bounded \
|
|
"dd if='$smoke_mount/payload.bin' bs=1 skip=4093 count=131071 2>/dev/null | sha256 -q" \
|
|
>"$artifacts/guest-range-sha256.txt"
|
|
cmp "$artifacts/expected-range-sha256.txt" "$artifacts/guest-range-sha256.txt" || \
|
|
pre15_dut_fail 'LZ4 smoke cross-pcluster partial range mismatch'
|
|
fi
|
|
|
|
pre15_guest_ssh_bounded dmesg >"$artifacts/guest-dmesg.txt"
|
|
if grep -Eqi 'panic:|lock order reversal|witness.*warning|use-after-free' \
|
|
"$artifacts/guest-dmesg.txt"; then
|
|
pre15_dut_fail "$PRE15_SMOKE_CODEC smoke observed kernel failure evidence"
|
|
fi
|
|
printf '%s\n' \
|
|
"SMOKE-$PRE15_SMOKE_CODEC PASS mode=zstdio$config deadline=$case_timeout" \
|
|
'readonly mount, exact file hashes/sizes, readdir set, and owned cleanup exercised'
|