mirror of
https://github.com/Klipper4FlashForge/firmware.git
synced 2026-10-22 21:32:16 -05:00
Two strands, both landing here because they had grown into each other in the
working tree.
The printer replica: the printer's real rootfs.squashfs chrooted under
qemu-mipsel, with /usr/prog and /usr/data from the factory image, so a package
is installed by FlashForge's own updater running on the printer's own busybox,
tar, md5sum and unTar. There are no stubs -- if the real prog partition is
missing the harness refuses to run rather than test against mocks. A release
workflow is blocked on it.
The lanes: a file's directory now says whether it can ever reach a printer.
payload/, assets/ ship
bin/, profiles/ build the package
test/, docs/ neither, ever
* the replica's own infrastructure moved out of bin/ and docker/ and in
beside the harness it belongs to (test/extract-rootfs.sh,
test/build-printer-image.sh, test/printer/Dockerfile{,.full})
* the Makefile has two runners: only RUNSIM gets the docker socket and the
replica's variables, so a build cannot reach the docker daemon at all
* replica settings moved to test.env, which nothing in a package reads
* build-time flags renamed BUILD_* (APPLY, REPORT, KLIPPER, TOOLCHANGE,
MAINSAIL, HELIX). MOD_* now means only the runtime switches written into
anvil.conf and re-read by the printer at every boot
* verify.sh fails if any file in a package is byte-identical to one in
bin/, test/, docker/ or profiles/ -- by content, because a name blacklist
would trip over whatever Mainsail happens to call common.sh
Fixed while mapping it:
* BUILD_REPORT was read only inside the BUILD_APPLY=0 branch, so four
profiles declared it and got nothing. It is honoured on both paths now,
and off outside probe: report.sh copies /etc, passwd and shadow onto the
USB stick, which is a diagnostic, not something to hand out.
* three checks in the brick lint had been quietly dead. Two were guarded on
a payload/boot.sh replaced by the firmwareExe wrapper long ago; the third
was the file glob itself, which matched neither firmwareExe nor the
init.d/S* scripts -- the UI wrapper and every service went unscanned. A
missing file is now a failure rather than a silent pass.
* run-tests.sh overwrote config.env and copied it back, leaving the config
you edited one crashed run away from being a fixture. It uses CONFIG_ENV.
* bin/make-uninstall.sh does not exist and never did; README, run-pre.sh and
full.env all pointed at it. Recovery is the stock package, which is what
test-recovery actually proves.
README is now for someone who wants to flash their printer: what it is, which
file, how to flash, what to do when it goes wrong. The rest moved to
docs/how-it-works.md, docs/building.md and docs/testing.md.
make test: 89 passed, 0 failed.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
92 lines
3.6 KiB
Bash
92 lines
3.6 KiB
Bash
#!/usr/bin/env bash
|
|
# Host-side launcher for the printer replica.
|
|
#
|
|
# test/printer-exec.sh <case-script> [name=package.tgz ...]
|
|
#
|
|
# The case script is executed by the printer's own busybox inside a chroot of
|
|
# the real extracted rootfs.squashfs, with MIPS binaries running under
|
|
# qemu-user. Named packages appear on the simulated USB stick as /mnt/<name>.
|
|
#
|
|
# BASE_PKG=<stock .tgz> installs stock firmware first, so /usr/prog holds the
|
|
# genuine klipper tree, unTar, app_startup.sh and firmwareExe rather than
|
|
# hand-written fakes.
|
|
#
|
|
# PROG_DUMP=<tar or dir> supplies a real /usr/prog taken off a printer
|
|
# (`tar -cf /mnt/prog.tar /usr/prog` over ssh). With one, the replica has no
|
|
# invented files left at all.
|
|
set -uo pipefail
|
|
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
CASE="${1:?usage: printer-exec.sh <case-script> [name=pkg.tgz ...]}"; shift
|
|
|
|
DOCKER=docker
|
|
command -v docker >/dev/null 2>&1 || DOCKER=docker.exe
|
|
command -v $DOCKER >/dev/null 2>&1 || { echo " SKIP: docker not available"; exit 0; }
|
|
$DOCKER info >/dev/null 2>&1 || { echo " SKIP: docker daemon not running"; exit 0; }
|
|
|
|
# PRINTER_IMAGE names a prebuilt image that already carries the firmware --
|
|
# rootfs, /usr/prog and /usr/data baked in by test/build-printer-image.sh. With
|
|
# one, nothing local is needed and a run skips the unpack entirely.
|
|
IMAGE="${PRINTER_IMAGE:-}"
|
|
PREBUILT=1
|
|
if [ -z "$IMAGE" ]; then
|
|
PREBUILT=0
|
|
IMAGE=creator5-printer-sim
|
|
if [ ! -d "$ROOT/work/rootfs/bin" ]; then
|
|
echo " SKIP: no printer rootfs -- run 'make rootfs' first (needs the stock"
|
|
echo " package), or set PRINTER_IMAGE to a prebuilt printer image"
|
|
exit 0
|
|
fi
|
|
# Always rebuild: it is a cache hit in about a second, and a stale image
|
|
# silently testing yesterday's harness is not a trade worth making.
|
|
$DOCKER build -q -t "$IMAGE" -f "$ROOT/test/printer/Dockerfile" "$ROOT/test/printer" >/dev/null \
|
|
|| { echo " FAIL: could not build $IMAGE"; exit 1; }
|
|
fi
|
|
|
|
# Stage every input inside the repo: the docker daemon resolves bind-mount
|
|
# paths on the host, and the repo is the one directory guaranteed to exist
|
|
# there under the same name.
|
|
STAGE="$ROOT/work/.sim"
|
|
rm -rf "$STAGE"; mkdir -p "$STAGE/pkgs"
|
|
trap 'rm -rf "$STAGE"' EXIT # the staged packages are ~80MB each
|
|
cp "$CASE" "$STAGE/case.sh"
|
|
|
|
PKGS=""
|
|
for spec in "$@"; do
|
|
name="${spec%%=*}"; path="${spec#*=}"
|
|
cp "$path" "$STAGE/pkgs/$name"
|
|
PKGS="$PKGS $name=/pkgs/$name"
|
|
done
|
|
|
|
BASE_ARG=""
|
|
if [ -n "${BASE_PKG:-}" ]; then
|
|
cp "$BASE_PKG" "$STAGE/pkgs/base.tgz"
|
|
BASE_ARG="/pkgs/base.tgz"
|
|
fi
|
|
|
|
DUMP_MOUNT=""
|
|
DUMP_ARG=""
|
|
if [ "$PREBUILT" = 0 ] && [ -n "${PROG_DUMP:-}" ] && [ -e "$PROG_DUMP" ]; then
|
|
DUMP_ABS="$(cd "$(dirname "$PROG_DUMP")" && pwd)/$(basename "$PROG_DUMP")"
|
|
DUMP_MOUNT="-v $DUMP_ABS:/progdump:ro"
|
|
DUMP_ARG="/progdump"
|
|
fi
|
|
|
|
# --privileged is needed for exactly two things: registering the binfmt handler
|
|
# for the printer's MIPS binaries, and building the mount layout that gives the
|
|
# replica a read-only root with writable prog/data partitions.
|
|
ROOTFS_MOUNT="-v $ROOT/work/rootfs:/rootfs:ro"
|
|
[ "$PREBUILT" = 1 ] && ROOTFS_MOUNT="" # the image carries its own firmware
|
|
|
|
# shellcheck disable=SC2086
|
|
$DOCKER run --rm -i --privileged \
|
|
$ROOTFS_MOUNT \
|
|
-v "$STAGE/pkgs:/pkgs:ro" \
|
|
-v "$STAGE/case.sh:/case.sh:ro" \
|
|
-v "$ROOT/payload:/payload:ro" \
|
|
-e "FF_KEY=${FF_KEY:-FFP0331&*%root}" \
|
|
-e "BASE_PKG=$BASE_ARG" \
|
|
-e "PKGS=$PKGS" \
|
|
-e "PROG_DUMP=$DUMP_ARG" $DUMP_MOUNT \
|
|
-e "PROG_MB=${PROG_MB:-}" -e "DATA_MB=${DATA_MB:-}" -e "SIM_VERBOSE=${SIM_VERBOSE:-0}" \
|
|
"$IMAGE" /case.sh
|