Files
firmware/docs/hardware-testing.md
T
Oleksandr ShyshatskyiandClaude Opus 5 57c776ee63 test/ is deleted; qa/ is the only suite
The eight files were already gone from the working tree. What this commit does
is everything that had to follow them, because nothing else had been updated
and three of the four things pointing at test/ were on a build or release path.

WHAT WAS STILL WIRED TO IT

  pkgs/klipper/build.sh   ran test/test-chelper.py under `|| pkg_die`. With the
                          file gone `make packages` would have died on every
                          klipper build.
  bin/verify.sh           ran the same script and read a non-zero exit as
                          "c_helper.so does not match the shipped klippy tree
                          (stale build)" -- a false red on every release verify
                          rather than an error about a missing file. Its
                          ship-boundary check also globbed `find bin test
                          docker`; that is `find bin docker` now.
  pytest.ini              testpaths = test, so a bare `pytest` collected
                          nothing at all. It is `qa` now, which is what the
                          comment above it was already describing.
  qa/static/              PY_GLOBS listed test/*.py and test/integration/*.py,
    test_shell_syntax.py  and _files() makes an empty glob a collection error
                          on purpose -- so the whole static lane failed to
                          collect, taking 93 unrelated tests with it.

Also dropped: the `pytest -- the host-side tree` step in ci.yml, the `test-py`
target with its .PHONY entry and two help lines, and qa/conftest.py's opening
paragraph explaining why qa/ sat beside test/ rather than inside it.

THE CHELPER SYMBOL CHECK IS GONE, NOT MOVED

It compared the .so's dynamic symbols against what klippy cdefs, and it was the
only check for a c_helper.so built from older sources than the klippy tree
beside it -- the failure that shipped once and bricked klippy startup on
hardware, because cffi resolves lazily and a stale .so imports cleanly.
qa/replica/test_install.py covers the ELF arch and nan2008 and nothing else.

What stands in its place is structural rather than a gate: pkgs/klipper
compiles the .so from the chelper sources of the very tree it ships, so the
mismatch is not something the recipe can produce. The comments in
pkgs/klipper/build.sh and docs/building.md now say that is the whole defence.

DOCS

docs/testing.md's "what is left in test/" section is now "test/ is gone", and
it names what went uncovered rather than leaving it to be found: the tool-frame
arithmetic in ff_toolchange, the chamber macros' per-model branching, the stamp
discipline in ff-startup.py, and the verification G-code against the shipped
macros. docs/hardware-testing.md said `make test-py` keeps the two
gcode/creator5-*.gcode files honest; it now says nothing does, and to read them
by hand when a macro is renamed. Paths corrected in docs/building.md,
docs/printer-replica.md and docs/qa-migration.md's intro.

Verified: `pytest` collects 366; qa/static is 136 passed, up from 43 because
the lane could not collect before this. Its 110 errors are this checkout's
missing vendor/opkg-utils, the same cause before and after. bin/verify.sh,
pkgs/klipper/build.sh and the Makefile parse; ci.yml is valid YAML.

Not touched, and stale before this commit: tools/python/README.md and
tools/supervisor/README.md still document test/integration/printer/case-*.sh
and a printer-exec.py that earlier commits removed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016bLGYpVAeVzAX6NeAxcU42
2026-08-30 01:10:24 +03:00

4.3 KiB

Hardware testing

CI installs the package into a replica of the printer -- the real rootfs.squashfs running under qemu-mipsel, on the printer's own busybox and unTar (see printer-replica.md) -- and proves the machine would still boot. What it cannot do is drive the screen, the MCUs, the toolchanger or a print. This is the on-hardware procedure.

There is one flash: the firmware package for your model.

Rule: have the stock FlashForge package for your model on a spare stick before you flash anything. Flashing it back is the uninstall, and it is the only recovery step that needs nothing but a USB port — no ssh, no screen.

It used to be proven by make test-recovery, which installed the mod into the replica and flashed the stock package over it. That gate has been retired and nothing has replaced it yet — see qa-migration.md. It passed on its last run, but treat the rollback as unverified against the current build.


Step zero: check the model gate

Every package carries a gate. Its runFirmwareExe.sh has MACHINE= / PID= baked in, and compares them against the values app_startup.sh passes from the firmware already on the printer. A mismatch is refused with "Firmware does not match machine type" — it will not install, and it is not a valid recovery image either.

Model MACHINE PID
Creator 5 Creator5 0028
Creator 5 Pro Creator5Pro 0029

The gate is not cosmetic: the two models ship different firmwareExe binaries, so a package must be built from the stock package for its own model. make release builds both.

Find yours in Settings → About, or in /usr/data/firmwareRes/config/general.json (machineName), and set TARGET_MACHINE in config.env. Then:

make build && make verify          # one model
make release                       # both, into dist/

verify.sh fails loudly on a mismatch. You must start from a stock package built for your own model — the mod inherits the gate from whatever package you unpack.

Before the first flash

  • Put a copy of the stock FlashForge package for your model on a spare USB stick and keep it physically separate. That is your recovery image: flashing it restores every file the mod touches. Check it is the right model first — see above.
  • Note your printer's serial number (Settings → About). The factory image restores a placeholder serial and you may need to put yours back.
  • Confirm you can reach the printer's IP.
  • make qa passes.
  • make rootfs && make qa-replica passes — this parses every script that will run on the printer using the printer's own busybox ash.

Two USB sticks, FAT32, both packages at the root of the stick (not in a folder). Ship both filenames (Creator5-* and Creator5Pro-*): the Pro's boot script globs Creator5Pro-*.tgz, the non-Pro globs Creator5-*.tgz.


The flash

One flash brings up everything: a root password you know, Mainsail and moonraker, the forked Klipper with the toolchanger extras, and HelixScreen on the touchscreen in place of FlashForge's UI.

From here the procedure is the one an owner follows, and it is written for them rather than repeated here:

Installing the flash itself, the first boot, the root password
Your first print the go/no-go checks, calibration, and the two files under gcode/
Support the logs, and the way back to stock

What follows is the part that is ours rather than theirs: keeping those two verification files honest as the macros change.

Keeping the verification files honest

Nothing checks them automatically any more. make test-py used to: every command in them had to be one the mod's Klipper config or pkgs/klipper/payload/klipper/klippy/extras/ defines (bar an explicit allowlist of Klipper built-ins, currently just SET_PRESSURE_ADVANCE), TOOLS= had to list every tool the feature print uses, and the safe file's own lines had to stay cold and above Z50. That check went with the test/ tree.

So a renamed macro now breaks the print rather than the suite. If you rename or remove a macro, read gcode/creator5-safe-moves.gcode and gcode/creator5-feature-test.gcode before you ship it.