test: land firmware host-test build scaffolding (Makefile, .gitignore, sanity)
Some checks are pending
CI Benchmark - Fusion Loop Timing / Fusion Loop Timing Benchmark (push) Waiting to run
Some checks are pending
CI Benchmark - Fusion Loop Timing / Fusion Loop Timing Benchmark (push) Waiting to run
The per-test setjmp/longjmp recovery loop in test_runner.c (main()) was
already delivered by sibling bead bf-bq9 (commit 549dc1f) and verified to
satisfy bf-53ut's contract: a failing assertion longjmps back to main()'s
setjmp, which falls through to advance the loop, so a failure in test N
never blocks tests N+1..end (proven with a temp failing-test followed by a
passing test — both ran and the process completed without aborting).
This commit lands the three harness files that were staged but absent from
HEAD (Makefile, .gitignore, test_sanity.c) so that 'make -C firmware/test
test' — the command bf-53ut's acceptance invokes — actually builds and runs
against the committed tree. Without them the committed test_runner.c could
not be built from a fresh clone.
Verified against the bf-53ut acceptance criteria:
- gcc -std=c11 -Wall -Wextra (-Werror): clean; no -Wclobbered/setjmp warnings
- normal suite: PASS, exit 0
- failing test + later passing test: both per-test lines print, process
completes (non-fatal assertions)
- no changes to firmware/main/* or firmware/CMakeLists.txt
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
549dc1f179
commit
c66f62e616
3 changed files with 84 additions and 0 deletions
3
firmware/test/.gitignore
vendored
Normal file
3
firmware/test/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Build output of `make -C firmware/test test` (BUILD_DIR = build).
|
||||
# The runner binary and object artifacts land here; never tracked.
|
||||
/build/
|
||||
58
firmware/test/Makefile
Normal file
58
firmware/test/Makefile
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
# ============================================================================
|
||||
# Spaxel firmware host test harness — Makefile
|
||||
# ============================================================================
|
||||
#
|
||||
# Build & run the whole suite, in one command, from the repo root:
|
||||
#
|
||||
# make -C firmware/test test
|
||||
#
|
||||
# That compiles every test_*.c in this directory together with test_runner.c
|
||||
# using plain gcc (no ESP-IDF toolchain) and runs the resulting binary. The
|
||||
# runner returns non-zero if ANY assertion fails, and make propagates that exit
|
||||
# code, so the command is safe to wire straight into CI.
|
||||
#
|
||||
# See test_runner.h for the gcc-harness rationale (decision record: bead bf-21t;
|
||||
# this build-out is the split of parent bead bf-4ne into child bf-56v).
|
||||
#
|
||||
# Adding a test: drop firmware/test/test_<thing>.c that uses the TEST() macro
|
||||
# from test_runner.h. The wildcard below picks it up automatically; its TEST()
|
||||
# self-registers via a GCC constructor — no SOURCES edit, no runner change.
|
||||
# ============================================================================
|
||||
|
||||
CC ?= gcc
|
||||
CFLAGS ?= -std=c11 -Wall -Wextra -O2 -g
|
||||
LDFLAGS ?=
|
||||
|
||||
# Every self-registering test unit, plus the runner that holds main(). The
|
||||
# wildcard means a new test_*.c is compiled and linked with zero edits here.
|
||||
#
|
||||
# test_runner.c is itself matched by the test_*.c glob, so it is filtered out of
|
||||
# the test set and added back exactly once as RUNNER_SRC — otherwise main() and
|
||||
# the registry functions would be defined twice and the link would fail.
|
||||
RUNNER_SRC := test_runner.c
|
||||
TEST_SRCS := $(filter-out $(RUNNER_SRC), $(wildcard test_*.c))
|
||||
ALL_SRCS := $(TEST_SRCS) $(RUNNER_SRC)
|
||||
|
||||
BUILD_DIR := build
|
||||
BIN := $(BUILD_DIR)/spaxel_host_tests
|
||||
|
||||
# Object files (not archives) are linked directly, so every test_*.c's TEST()
|
||||
# constructor is retained and runs at load — no --whole-archive needed. Only
|
||||
# unused *archive* members get dropped by the linker, never direct .o files.
|
||||
.PHONY: test build run clean
|
||||
|
||||
# Default goal: the documented single command. `build` produces the binary,
|
||||
# `run` executes it; make returns the binary's exit code, so failures surface.
|
||||
test: build run
|
||||
|
||||
build: $(BIN)
|
||||
|
||||
$(BIN): $(ALL_SRCS) test_runner.h
|
||||
@mkdir -p $(BUILD_DIR)
|
||||
$(CC) $(CFLAGS) $(ALL_SRCS) -o $@ $(LDFLAGS)
|
||||
|
||||
run: $(BIN)
|
||||
./$(BIN)
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILD_DIR)
|
||||
23
firmware/test/test_sanity.c
Normal file
23
firmware/test/test_sanity.c
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Sanity test for the Spaxel firmware host test harness.
|
||||
*
|
||||
* This is the minimal passing test that proves the harness wires up end to end:
|
||||
* the TEST() macro self-registers via its GCC constructor, the runner drives the
|
||||
* registered test, and ASSERT_EQ reports correctly.
|
||||
*
|
||||
* Real module tests (nvs/csi/prov logic extractions + binary-format contracts)
|
||||
* are deliberately NOT here — they are added by the sibling beads that follow.
|
||||
* Keeping this bead (bf-56v) to scaffolding + a single sanity test is what lets
|
||||
* the "compiles + runs + exits non-zero on failure" contract be verified in
|
||||
* isolation before any module behavior is exercised.
|
||||
*/
|
||||
#include "test_runner.h"
|
||||
|
||||
/*
|
||||
* 1 + 1 == 2: the smallest possible assertion. If this fails, the harness itself
|
||||
* is broken, not the firmware logic under test.
|
||||
*/
|
||||
TEST(arithmetic_sanity)
|
||||
{
|
||||
ASSERT_EQ(1 + 1, 2);
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue