Magnemite
Development

Testing without hardware

200 fake boxes that exercise the real download, hash and extraction paths.

The agent's -fake-root mode stubs out pm, dumpsys and getprop and nothing else — the download, the sha256 check and the .apkm extraction are all real. So a fake fleet exercises the actual pipeline, not a mock of it.

make agent
./scripts/fake-fleet.sh 200 <enrollment-token>

On Windows:

./scripts/build-agent.ps1
./scripts/fake-fleet.ps1 -Count 200 -Token <token>

Each fake box enrolls with its own serial, opens its own socket and shows up in the fleet table like any other device.

Failure injection

Lives in agent/internal/sys/fake.go, driven by environment variables:

VariableEffect
MAGNEMITE_FAKE_COMMIT_ERRORText that install-commit fails with
MAGNEMITE_FAKE_COMMIT_ERROR_ONCEFail only the first commit, to exercise the uninstall fallback
MAGNEMITE_FAKE_FREE_BYTESOverride free space, to trip the space gate
MAGNEMITE_FAKE_INSTALL_MSHow long a commit pretends to take

Where a pushed config lands

/data/local/tmp/aegis_config.json is not a path a laptop has, so a fake box writes under its own state file instead, separators flattened into the name:

.dev/fleet/fake-001.files/data_local_tmp_aegis_config.json

The whole path is exercised — the mkdir, the temp file, the rename, the sha256 read back — so a MITM config written by a deploy can be verified end to end, placeholder substitution included, without a box in the room.

Testing adb enrollment without a box

Adding boxes over adb splits into three pieces, and two of them need no hardware at all.

The probe runs against a Redroid container, which is a real adb target: it runs adbd on 5555 and this project's image ships su. Connecting, getprop, the device/unauthorized distinction and the root check are all genuine against one.

The back half runs against a fake agent. Enrol a box, take the token out of the enrollment row's config step, and start a fake with the serial the hub expects:

./scripts/fake-fleet.ps1 -Count 1 -Token <the box's token>

It enrols, the BoxEnroll row goes WAITING → DONE, and the box lands in the group and under the name the dialog asked for — which is the whole loop.

What still needs one real box is magisk --install-module and the reboot. On an x86_64 development machine a Redroid container is x86_64 Android, so customize.sh aborts on the ABI — the module zip carries arm64 and arm only — and a container has no kernel to restart.

What this is good for

  • Scheduler behaviour under load. 200 devices against a max concurrent jobs of 10 (Settings → Tuning) is the only honest way to see the queue drain.
  • The canary path. Fail one commit and watch the rollout park at PAUSED.
  • The clean-install fallback. ..._ONCE makes the agent take the uninstall-and-reinstall branch on demand.
  • Stall handling. A long MAGNEMITE_FAKE_INSTALL_MS plus a low job stall timeout (Settings → Tuning) reproduces a re-queue in under a minute.

A fake fleet downloads real bundles. 200 fakes pulling a 172 MB .apkm is ~35 GB through your own machine — cap the count, or point them at a small artifact.

On this page