tests
dagger function so it can be invoked individually during TDD; All wires themup for parallel execution under `dagger call all`. The four sub-aggregators
(Validation, Firmware, Boot, Networking) each carry `+check` so CI schedules
them onto their own runners.
Installation
dagger install github.com/z5labs/devex/daggerverse/qemu/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453Entrypoint
Return Type
Tests Example
dagger -m github.com/z5labs/devex/daggerverse/qemu/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
func (m *MyModule) Example() *dagger.Tests {
return dag.
Tests()
}@function
def example() -> dagger.Tests:
return (
dag.tests()
)@func()
example(): Tests {
return dag
.tests()
}Types
Tests 🔗
all() 🔗
All runs every qemu test as a convenience for local dagger call all
invocations. CI does NOT call All: each sub-aggregator below carries its own
+check directive, so GH Actions schedules each onto its own runner in
parallel — running All on top would double-bill the same work.
Return Type
Void !Arguments
| Name | Type | Default Value | Description |
|---|---|---|---|
| parallel | Integer ! | 0 | No description provided |
Example
dagger -m github.com/z5labs/devex/daggerverse/qemu/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
all --parallel integerfunc (m *MyModule) Example(ctx context.Context, parallel int) {
return dag.
Tests().
All(ctx, parallel)
}@function
async def example(parallel: int) -> None:
return await (
dag.tests()
.all(parallel)
)@func()
async example(parallel: number): Promise<void> {
return dag
.tests()
.all(parallel)
}bareMetal() 🔗
BareMetal runs the bare-metal firmware + semihosting tests: boot a tiny freestanding Cortex-M3 firmware (built reproducibly via the zig module) on the MCU-class lm3s6965evb machine and assert that semihosting SYS_WRITE0 reaches the serial console and SYS_EXIT surfaces as a guest exit code. These are fast TCG boots (the firmware writes a marker and exits immediately).
Return Type
Void !Arguments
| Name | Type | Default Value | Description |
|---|---|---|---|
| parallel | Integer ! | 0 | No description provided |
Example
dagger -m github.com/z5labs/devex/daggerverse/qemu/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
bare-metal --parallel integerfunc (m *MyModule) Example(ctx context.Context, parallel int) {
return dag.
Tests().
Baremetal(ctx, parallel)
}@function
async def example(parallel: int) -> None:
return await (
dag.tests()
.baremetal(parallel)
)@func()
async example(parallel: number): Promise<void> {
return dag
.tests()
.bareMetal(parallel)
}bareMetalBootsAndCapturesSerial() 🔗
BareMetalBootsAndCapturesSerial verifies a semihosting firmware’s SYS_WRITE0 marker reaches the serial console through RunStatus, Run, and WaitForLine.
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/qemu/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
bare-metal-boots-and-captures-serialfunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Baremetalbootsandcapturesserial(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.baremetalbootsandcapturesserial()
)@func()
async example(): Promise<void> {
return dag
.tests()
.bareMetalBootsAndCapturesSerial()
}bareMetalExitCodeNonZeroOnFail() 🔗
BareMetalExitCodeNonZeroOnFail verifies a firmware that calls SYS_EXIT with a non-zero code yields the corresponding non-zero RunStatus().ExitCode.
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/qemu/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
bare-metal-exit-code-non-zero-on-failfunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Baremetalexitcodenonzeroonfail(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.baremetalexitcodenonzeroonfail()
)@func()
async example(): Promise<void> {
return dag
.tests()
.bareMetalExitCodeNonZeroOnFail()
}bareMetalExitCodeZeroOnPass() 🔗
BareMetalExitCodeZeroOnPass verifies a firmware that calls SYS_EXIT(0) yields RunStatus().ExitCode == 0.
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/qemu/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
bare-metal-exit-code-zero-on-passfunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Baremetalexitcodezeroonpass(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.baremetalexitcodezeroonpass()
)@func()
async example(): Promise<void> {
return dag
.tests()
.bareMetalExitCodeZeroOnPass()
}bareMetalRejectsNilFirmware() 🔗
BareMetalRejectsNilFirmware verifies a nil firmware is rejected. The Dagger SDK binding panics via assertNotNil before the call leaves the test module; recover and assert the panic mentions the rejected argument.
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/qemu/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
bare-metal-rejects-nil-firmwarefunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Baremetalrejectsnilfirmware(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.baremetalrejectsnilfirmware()
)@func()
async example(): Promise<void> {
return dag
.tests()
.bareMetalRejectsNilFirmware()
}bareMetalRejectsUnknownArch() 🔗
BareMetalRejectsUnknownArch verifies BareMetal errors for an arch with no bare-metal (MCU) profile — e.g. a SoC arch like X86_64 that Linux/Disk accept but BareMetal does not.
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/qemu/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
bare-metal-rejects-unknown-archfunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Baremetalrejectsunknownarch(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.baremetalrejectsunknownarch()
)@func()
async example(): Promise<void> {
return dag
.tests()
.bareMetalRejectsUnknownArch()
}boot() 🔗
Boot runs the real-kernel boot tests against the Alpine aarch64 netboot kernel (slow TCG boots).
Return Type
Void !Arguments
| Name | Type | Default Value | Description |
|---|---|---|---|
| parallel | Integer ! | 0 | No description provided |
Example
dagger -m github.com/z5labs/devex/daggerverse/qemu/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
boot --parallel integerfunc (m *MyModule) Example(ctx context.Context, parallel int) {
return dag.
Tests().
Boot(ctx, parallel)
}@function
async def example(parallel: int) -> None:
return await (
dag.tests()
.boot(parallel)
)@func()
async example(parallel: number): Promise<void> {
return dag
.tests()
.boot(parallel)
}defaultsBootArm64Kernel() 🔗
DefaultsBootArm64Kernel verifies the documented defaults boot a working VM: arch=AARCH64 with empty machine/cpu must resolve to virt + cortex-a53 and reach userspace.
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/qemu/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
defaults-boot-arm-6-4-kernelfunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Defaultsbootarm64kernel(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.defaultsbootarm64kernel()
)@func()
async example(): Promise<void> {
return dag
.tests()
.defaultsBootArm64Kernel()
}diskRejectsNilImage() 🔗
DiskRejectsNilImage verifies a nil disk image is rejected (assertNotNil panic, as above).
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/qemu/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
disk-rejects-nil-imagefunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Diskrejectsnilimage(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.diskrejectsnilimage()
)@func()
async example(): Promise<void> {
return dag
.tests()
.diskRejectsNilImage()
}endpointRejectsUnforwardedPort() 🔗
EndpointRejectsUnforwardedPort verifies Endpoint errors for a port that was not in the machine’s tcpPorts.
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/qemu/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
endpoint-rejects-unforwarded-portfunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Endpointrejectsunforwardedport(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.endpointrejectsunforwardedport()
)@func()
async example(): Promise<void> {
return dag
.tests()
.endpointRejectsUnforwardedPort()
}endpointReturnsForwardedHostPort() 🔗
EndpointReturnsForwardedHostPort verifies Endpoint returns host:port for a forwarded port.
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/qemu/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
endpoint-returns-forwarded-host-portfunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Endpointreturnsforwardedhostport(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.endpointreturnsforwardedhostport()
)@func()
async example(): Promise<void> {
return dag
.tests()
.endpointReturnsForwardedHostPort()
}firmware() 🔗
Firmware runs the run-to-completion serial-capture tests against a tiny custom-init initramfs (fast under TCG).
Return Type
Void !Arguments
| Name | Type | Default Value | Description |
|---|---|---|---|
| parallel | Integer ! | 0 | No description provided |
Example
dagger -m github.com/z5labs/devex/daggerverse/qemu/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
firmware --parallel integerfunc (m *MyModule) Example(ctx context.Context, parallel int) {
return dag.
Tests().
Firmware(ctx, parallel)
}@function
async def example(parallel: int) -> None:
return await (
dag.tests()
.firmware(parallel)
)@func()
async example(parallel: number): Promise<void> {
return dag
.tests()
.firmware(parallel)
}linuxBootReachesUserspace() 🔗
LinuxBootReachesUserspace verifies a real Alpine aarch64 kernel hands off to
PID 1 in userspace: the kernel logs the /init handoff and userspace then runs
a working uname syscall.
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/qemu/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
linux-boot-reaches-userspacefunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Linuxbootreachesuserspace(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.linuxbootreachesuserspace()
)@func()
async example(): Promise<void> {
return dag
.tests()
.linuxBootReachesUserspace()
}linuxRejectsNilKernel() 🔗
LinuxRejectsNilKernel verifies a nil kernel is rejected. The Dagger SDK binding panics via assertNotNil before the call leaves the test module; recover and assert the panic mentions the rejected argument.
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/qemu/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
linux-rejects-nil-kernelfunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Linuxrejectsnilkernel(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.linuxrejectsnilkernel()
)@func()
async example(): Promise<void> {
return dag
.tests()
.linuxRejectsNilKernel()
}networking() 🔗
Networking runs the service-bind end-to-end tests: boot a guest that brings up networking and serves a forwarded port, then prove reachability and teardown through WithServiceBinding. These are slow TCG boots plus real networking.
Return Type
Void !Arguments
| Name | Type | Default Value | Description |
|---|---|---|---|
| parallel | Integer ! | 0 | No description provided |
Example
dagger -m github.com/z5labs/devex/daggerverse/qemu/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
networking --parallel integerfunc (m *MyModule) Example(ctx context.Context, parallel int) {
return dag.
Tests().
Networking(ctx, parallel)
}@function
async def example(parallel: int) -> None:
return await (
dag.tests()
.networking(parallel)
)@func()
async example(parallel: number): Promise<void> {
return dag
.tests()
.networking(parallel)
}runCapturesFirmwareSerial() 🔗
RunCapturesFirmwareSerial verifies Run boots the firmware to completion and returns its serial console.
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/qemu/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
run-captures-firmware-serialfunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Runcapturesfirmwareserial(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.runcapturesfirmwareserial()
)@func()
async example(): Promise<void> {
return dag
.tests()
.runCapturesFirmwareSerial()
}runShouldNotBeCached() 🔗
RunShouldNotBeCached verifies two Run calls on one Machine re-execute QEMU rather than cache-hitting: each boot emits fresh /dev/urandom bytes, so the two serial consoles must differ.
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/qemu/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
run-should-not-be-cachedfunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Runshouldnotbecached(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.runshouldnotbecached()
)@func()
async example(): Promise<void> {
return dag
.tests()
.runShouldNotBeCached()
}serialLogMaterializesFile() 🔗
SerialLogMaterializesFile verifies SerialLog stages the serial console as a readable *dagger.File.
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/qemu/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
serial-log-materializes-filefunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Seriallogmaterializesfile(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.seriallogmaterializesfile()
)@func()
async example(): Promise<void> {
return dag
.tests()
.serialLogMaterializesFile()
}serviceForwardedPortReachable() 🔗
ServiceForwardedPortReachable boots a guest that brings up networking and listens on a runtime-minted port, forwards it over slirp hostfwd, binds the machine into a fresh consumer container, and asserts the port is reachable — proving hostfwd + slirp + WithServiceBinding wiring end-to-end.
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/qemu/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
service-forwarded-port-reachablefunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Serviceforwardedportreachable(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.serviceforwardedportreachable()
)@func()
async example(): Promise<void> {
return dag
.tests()
.serviceForwardedPortReachable()
}stopHaltsService() 🔗
StopHaltsService proves Stop’sbacking service (the postgres EndpointShouldNotBeCached lifecycle analog). The guest serves a per-boot identity token. We pin the service up with an explicit Start so it stays one instance across reads, read the token, Stop the machine, then read again — the second read re-binds and, because Stop killed the original VM, gets a fresh boot with a different token. A no-op Stop would leave the pinned instance serving the same token, so an unchanged token fails the test. This is robust to fast TCG boots (it relies on the restart, not on out-racing it); the per-read nonce keeps the two reads from cache-colliding.
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/qemu/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
stop-halts-servicefunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Stophaltsservice(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.stophaltsservice()
)@func()
async example(): Promise<void> {
return dag
.tests()
.stopHaltsService()
}validation() 🔗
Validation runs the pure input-rejection and accessor tests. None boot a guest, so they’re fast and safe to fan out unbounded.
Return Type
Void !Arguments
| Name | Type | Default Value | Description |
|---|---|---|---|
| parallel | Integer ! | 0 | No description provided |
Example
dagger -m github.com/z5labs/devex/daggerverse/qemu/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
validation --parallel integerfunc (m *MyModule) Example(ctx context.Context, parallel int) {
return dag.
Tests().
Validation(ctx, parallel)
}@function
async def example(parallel: int) -> None:
return await (
dag.tests()
.validation(parallel)
)@func()
async example(parallel: number): Promise<void> {
return dag
.tests()
.validation(parallel)
}waitForLineMatchesFirmwareSerial() 🔗
WaitForLineMatchesFirmwareSerial verifies WaitForLine returns the console once the marker line appears.
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/qemu/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
wait-for-line-matches-firmware-serialfunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Waitforlinematchesfirmwareserial(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.waitforlinematchesfirmwareserial()
)@func()
async example(): Promise<void> {
return dag
.tests()
.waitForLineMatchesFirmwareSerial()
}