Testing Overview
Overview of spec-based automated testing for Astrobe Oberon programs
The gdbtestengine provides spec-based automated testing for Astrobe Oberon programs running on hardware. Declarative test specifications describe what to check or trace at specific procedure entry points. The engine runs inside GDB, sets breakpoints, collects values from registers and memory, and produces a timestamped report.
Testing requires an ELF file with DWARF debug data, built by gen-rdb and make-elf.
Workflow
The preparation steps are:
- compile and link with Astrobe (produces
.bin,.lst,.map) - gen-rdb Prog
.map– generates therdb/directory - make-elf Prog
.bin --debug– builds the ELF with debug data - start a GDB server – OpenOCD, matched to your debug probe
Quick Start
- write a
.specfile inrdb-gdb-tests/specs/ - connect GDB to the target:
arm-none-eabi-gdb-py3 Prog.elf
(gdb) target extended-remote localhost:3333
(gdb) load
- run the test:
(gdb) set environment SPEC init-test.spec
(gdb) run-test
The run-test command is a GDB alias defined in ~/.gdbinit that
sources the gdbtestengine. Reports are written to
rdb-gdb-tests/reports/.
For batch execution (no interactive prompt):
arm-none-eabi-gdb-py3 -batch
-ex "target extended-remote localhost:3333" \
-ex "load" \
-ex "set environment SPEC init-test.spec" \
-ex "run-test" Prog.elf
Example Spec
A spec file that checks argument values at procedure entry points during the program's initialisation phase:
-- SignalSync init-phase test spec
-- Tests known argument values at procedure entry points.
option timeout = 15
option max-hits = 20
-- Stop after seeing all init calls
stop after 10 hits
-- LED.Set is called with {LED.Pico} = 128 = 0x80
proc LED.Set
at entry
check arg leds = 128
-- Kernel.SetPeriod is called twice during init:
-- SetPeriod(50, 0) -- T0period=50, startAfter=0
-- SetPeriod(100, 100) -- T3period=100, startAfter=100
-- We trace both args to see the values.
proc Kernel.SetPeriod
at entry
trace arg period
trace arg startAfter
-- Cores.CoreId is a leaf proc with no args.
proc Cores.CoreId
at entry
trace local cid
Key elements:
option– configure timeout and maximum breakpoint hitsstop after N hits– terminate the test after N breakpoint hitsproc Module.Procedure– select a procedureat entry– location within the procedurecheck– verify a value (PASS/FAIL)trace– record a value (always PASS)
The spec language supports comparison operators (=, #, >, <,
>=, <=), cross-module constants, memory reads with field and
bit-range access, signed/unsigned control, NIL, and sentinel conditions
for controlling test execution windows.
The spec grammar covers the spec language in detail.
Testing Approach
The engine uses a descriptive, parallel model: the spec declares all procedures and checks up front, and the engine sets breakpoints on all of them simultaneously. The program runs freely; breakpoints fire in whatever order the program flow dictates. This means the spec writer does not need to predict execution order – the engine handles any interleaving.
Because hardware breakpoint slots are limited (typically 4-8 on Cortex-M), the engine rotates breakpoints automatically when more procedures are instrumented than slots are available. Each rotation replaces one breakpoint with another, so all procedures are eventually covered. This is transparent to the spec writer.
Sentinel directives (start, stop) control the execution window
– the phase of the program during which checks and traces are active.
This allows targeting specific execution phases (initialisation,
steady state, shutdown) without filtering unrelated hits.
Future extensions will add trigger conditions based on the call stack, sequential test ordering, and the composition of individual specs into test suites.
Constant Resolution
Spec files can reference exported Oberon constants using the
Module.Constant syntax. The engine resolves these from the .alst
files at start-up. Constants defined as literals or as expressions
within a single module resolve correctly. Constants that depend on
cross-module references in their defining expression (eg.
DEV0.FLASH_ACR = FLASH_BASE + 000H where FLASH_BASE comes from
another module) may not resolve. In such cases, use the constant from
the module that owns the base definition.
GDB Server Scripts
Ready-made scripts for starting GDB servers are in
<repo>/tools/server-scripts/. Each script has .sh and .cmd
variants. Start the appropriate server before running tests. See
External Tools for the full list and
installation details.
Last updated: 11 March 2026