# testbed/ — OpenWrt testbeds for balancer-lite-lua Two OpenWrt container testbeds, driven by the standard `openwrt-testbed` skill scripts (`skills/openwrt-testbed/scripts/`). ## 19.07 (skill default — image built by the skill) ```sh S=skills/openwrt-testbed/scripts $S/start.sh # builds openwrt-testbed:latest from shellspec/openwrt $S/stop.sh --rm # shut down + remove ``` Image: `openwrt-testbed:latest` (shellspec/openwrt 19.07.7 + luasocket). Note: it ships **no openssl** — run `opkg update && opkg install openssl-util` inside the container before `tests/sha256.lua` can pass. ## 23.05 (this directory) ```sh cd testbed ./download-2305.sh # fetches rootfs + .ipks (idempotent) docker build -f Dockerfile-2305 -t openwrt-testbed-2305:latest . OPENWRT_TESTBED_NAME=openwrt-testbed-2305 \ OPENWRT_TESTBED_IMAGE=openwrt-testbed-2305:latest \ $S/start.sh ``` Image: `openwrt-testbed-2305:latest`, built from the **official OpenWrt 23.05.6 x86_64 rootfs tarball** (downloads.openwrt.org) plus four .ipk payloads from the 23.05.6 feeds: | package | why | |---|---| | `lua` + `liblua5.1.5` | Lua **5.1.5** interpreter (OpenWrt 23.05's base `lua` package is still 5.1 — the "23.05 ships Lua 5.4" hypothesis is **false**; no 5.4-compat pass needed) | | `openssl-util` + `libopenssl3` + `ca-bundle` | `sha256.lua` shells out to `openssl dgst` | Why a scratch build: the official Docker Hub `openwrt/rootfs` repo has no 23.05 x86_64 tag (only 24.10/25.12), and `shellspec/openwrt` tops out at 19.07.7. Building from the official rootfs tarball keeps the testbed a real OpenWrt rootfs with real busybox/opkg/uci. Build gotchas (both hit in 2026-09): - busybox `tar` **cannot read `.ipk`** (ar archives) → extract on the host (host GNU tar handles them) and `COPY` the payload tree. - the `lua` .ipk alone is not enough: `lua` is a symlink to `lua5.1` which needs `liblua5.1.5` (separate .ipk) — without it `lua -v` dies with "Error loading shared library liblua.so.5.1.5". ## Running the balancerlite suite inside either testbed ```sh R=/root/.openclaw/workspace/balancer-lite-lua C=openwrt-testbed # or openwrt-testbed-2305 docker exec $C sh -c 'rm -rf /testbed/src /testbed/tests; mkdir -p /testbed/src' docker cp $R/src/balancerlite $C:/testbed/src/balancerlite docker cp $R/tests $C:/testbed/tests docker cp $R/testbed/testbed-runner.lua $C:/testbed/testbed-runner.lua docker exec $C sh -c 'cd /testbed && lua testbed-runner.lua' ``` Daemon dry-run: ```sh docker exec $C sh -c 'mkdir -p /tmp/bl_state' sed "s|/root/balancerlite|/tmp/bl_state|" $R/etc/config/balancerlite.example > /tmp/cfg docker cp /tmp/cfg $C:/testbed/etc-cfg docker exec $C sh -c 'cd /testbed && lua src/balancerlite/main.lua --config /testbed/etc-cfg --dry-run' # expect: "(DRY RUN)" banner + "exited after 1 cycles", rc=0 ``` ⚠️ `docker cp` gotcha: if the destination path **doesn't exist**, the source *directory itself* is copied under the destination name (nesting bug — the runner then silently tests a stale copy). Always `mkdir -p` the destination (or `rm -rf` + `mkdir -p` in one `sh -c`), and `md5sum` a file after the copy to verify.