tests
function so it can be invoked individually during TDD; All wires the hermeticsuite up for parallel execution and carries `+check` so CI schedules it.
The hermetic suite never touches real hardware: it covers input validation,
deterministic Plan rendering, chip-registry resolution (the real probe-rs
binary, no probe), a clean failure when no probe is present, and a
connection-counting proof that Run re-executes (never cached). The genuinely
hardware-dependent behaviors are the Hil* functions below — they carry NO
`+check` and are NOT in All, so CI never runs them; a flash-runner operator
invokes them against a real probe.
Installation
dagger install github.com/z5labs/devex/daggerverse/flash/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453Entrypoint
Return Type
Tests Example
dagger -m github.com/z5labs/devex/daggerverse/flash/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 the hermetic flash suite in parallel. It carries +check so CI
schedules it; the Hil* functions are deliberately excluded (no hardware in
CI).
Return Type
Void !Arguments
| Name | Type | Default Value | Description |
|---|---|---|---|
| parallel | Integer ! | 0 | No description provided |
Example
dagger -m github.com/z5labs/devex/daggerverse/flash/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)
}bridgeCommandRendersUsbipBind() 🔗
BridgeCommandRendersUsbipBind verifies BridgeCommand renders a host-side usbip bind command carrying the busid and port.
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/flash/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
bridge-command-renders-usbip-bindfunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Bridgecommandrendersusbipbind(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.bridgecommandrendersusbipbind()
)@func()
async example(): Promise<void> {
return dag
.tests()
.bridgeCommandRendersUsbipBind()
}chipInfoResolvesKnownChip() 🔗
ChipInfoResolvesKnownChip verifies a known chip resolves against probe-rs’s registry and the info block mentions the chip family.
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/flash/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
chip-info-resolves-known-chipfunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Chipinforesolvesknownchip(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.chipinforesolvesknownchip()
)@func()
async example(): Promise<void> {
return dag
.tests()
.chipInfoResolvesKnownChip()
}flasherHasProbeRs() 🔗
FlasherHasProbeRs asserts ProbeRs wires a probe-rs invocation (the flash backend is present), via a successful Plan render mentioning probe-rs.
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/flash/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
flasher-has-probe-rsfunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Flasherhasprobers(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.flasherhasprobers()
)@func()
async example(): Promise<void> {
return dag
.tests()
.flasherHasProbeRs()
}hilFlashRoundTrip() 🔗
HilFlashRoundTrip flashes firmware to a real target and verifies it, asserting both succeed. Provide a usbip host:port + busid (from BridgeCommand) or a remote endpoint, and the chip.
Return Type
Void !Arguments
| Name | Type | Default Value | Description |
|---|---|---|---|
| firmware | File ! | - | No description provided |
| chip | String ! | - | No description provided |
| usbip | String ! | "" | No description provided |
| busid | String ! | "" | No description provided |
| remote | String ! | "" | No description provided |
| format | String ! | "ELF" | No description provided |
| baseAddress | Integer ! | 0 | No description provided |
Example
dagger -m github.com/z5labs/devex/daggerverse/flash/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
hil-flash-round-trip --firmware file:path --chip string --usbip string --busid string --remote string --format string --base-address integerfunc (m *MyModule) Example(ctx context.Context, firmware *dagger.File, chip string, usbip string, busid string, remote string, format string, baseAddress int) {
return dag.
Tests().
Hilflashroundtrip(ctx, firmware, chip, usbip, busid, remote, format, baseAddress)
}@function
async def example(firmware: dagger.File, chip: str, usbip: str, busid: str, remote: str, format: str, baseaddress: int) -> None:
return await (
dag.tests()
.hilflashroundtrip(firmware, chip, usbip, busid, remote, format, baseaddress)
)@func()
async example(firmware: File, chip: string, usbip: string, busid: string, remote: string, format: string, baseAddress: number): Promise<void> {
return dag
.tests()
.hilFlashRoundTrip(firmware, chip, usbip, busid, remote, format, baseAddress)
}hilGdbServes() 🔗
HilGdbServes starts the probe-rs GDB stub against a real target and asserts a gdb client can reach it over the bound service.
Return Type
Void !Arguments
| Name | Type | Default Value | Description |
|---|---|---|---|
| firmware | File ! | - | No description provided |
| chip | String ! | - | No description provided |
| usbip | String ! | "" | No description provided |
| busid | String ! | "" | No description provided |
| remote | String ! | "" | No description provided |
| port | Integer ! | 1337 | No description provided |
Example
dagger -m github.com/z5labs/devex/daggerverse/flash/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
hil-gdb-serves --firmware file:path --chip string --usbip string --busid string --remote string --port integerfunc (m *MyModule) Example(ctx context.Context, firmware *dagger.File, chip string, usbip string, busid string, remote string, port int) {
return dag.
Tests().
Hilgdbserves(ctx, firmware, chip, usbip, busid, remote, port)
}@function
async def example(firmware: dagger.File, chip: str, usbip: str, busid: str, remote: str, port: int) -> None:
return await (
dag.tests()
.hilgdbserves(firmware, chip, usbip, busid, remote, port)
)@func()
async example(firmware: File, chip: string, usbip: string, busid: string, remote: string, port: number): Promise<void> {
return dag
.tests()
.hilGdbServes(firmware, chip, usbip, busid, remote, port)
}hilReset() 🔗
HilReset resets a real target.
Return Type
Void !Arguments
| Name | Type | Default Value | Description |
|---|---|---|---|
| firmware | File ! | - | No description provided |
| chip | String ! | - | No description provided |
| usbip | String ! | "" | No description provided |
| busid | String ! | "" | No description provided |
| remote | String ! | "" | No description provided |
Example
dagger -m github.com/z5labs/devex/daggerverse/flash/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
hil-reset --firmware file:path --chip string --usbip string --busid string --remote stringfunc (m *MyModule) Example(ctx context.Context, firmware *dagger.File, chip string, usbip string, busid string, remote string) {
return dag.
Tests().
Hilreset(ctx, firmware, chip, usbip, busid, remote)
}@function
async def example(firmware: dagger.File, chip: str, usbip: str, busid: str, remote: str) -> None:
return await (
dag.tests()
.hilreset(firmware, chip, usbip, busid, remote)
)@func()
async example(firmware: File, chip: string, usbip: string, busid: string, remote: string): Promise<void> {
return dag
.tests()
.hilReset(firmware, chip, usbip, busid, remote)
}hilVerifyMatches() 🔗
HilVerifyMatches verifies the on-target flash matches firmware without rewriting it.
Return Type
Void !Arguments
| Name | Type | Default Value | Description |
|---|---|---|---|
| firmware | File ! | - | No description provided |
| chip | String ! | - | No description provided |
| usbip | String ! | "" | No description provided |
| busid | String ! | "" | No description provided |
| remote | String ! | "" | No description provided |
Example
dagger -m github.com/z5labs/devex/daggerverse/flash/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
hil-verify-matches --firmware file:path --chip string --usbip string --busid string --remote stringfunc (m *MyModule) Example(ctx context.Context, firmware *dagger.File, chip string, usbip string, busid string, remote string) {
return dag.
Tests().
Hilverifymatches(ctx, firmware, chip, usbip, busid, remote)
}@function
async def example(firmware: dagger.File, chip: str, usbip: str, busid: str, remote: str) -> None:
return await (
dag.tests()
.hilverifymatches(firmware, chip, usbip, busid, remote)
)@func()
async example(firmware: File, chip: string, usbip: string, busid: string, remote: string): Promise<void> {
return dag
.tests()
.hilVerifyMatches(firmware, chip, usbip, busid, remote)
}planReflectsRemoteTransport() 🔗
PlanReflectsRemoteTransport asserts the remote plan carries the remote value and has no usbip-attach prefix. It asserts on the remote value, not the exact flag spelling, so it stays robust to probe-rs CLI evolution.
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/flash/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
plan-reflects-remote-transportfunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Planreflectsremotetransport(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.planreflectsremotetransport()
)@func()
async example(): Promise<void> {
return dag
.tests()
.planReflectsRemoteTransport()
}planRendersBinBaseAddress() 🔗
PlanRendersBinBaseAddress asserts the BIN plan renders –base-address with the hex address.
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/flash/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
plan-renders-bin-base-addressfunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Planrendersbinbaseaddress(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.planrendersbinbaseaddress()
)@func()
async example(): Promise<void> {
return dag
.tests()
.planRendersBinBaseAddress()
}planRendersElfDownload() 🔗
PlanRendersElfDownload asserts the ELF + usbip plan renders the probe-rs download argv with the usbip-attach prefix and no –base-address.
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/flash/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
plan-renders-elf-downloadfunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Planrenderselfdownload(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.planrenderselfdownload()
)@func()
async example(): Promise<void> {
return dag
.tests()
.planRendersElfDownload()
}probeRsRejectsBinWithoutBaseAddress() 🔗
ProbeRsRejectsBinWithoutBaseAddress verifies BIN with baseAddress=0 is rejected.
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/flash/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
probe-rs-rejects-bin-without-base-addressfunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Probersrejectsbinwithoutbaseaddress(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.probersrejectsbinwithoutbaseaddress()
)@func()
async example(): Promise<void> {
return dag
.tests()
.probeRsRejectsBinWithoutBaseAddress()
}probeRsRejectsBothTransports() 🔗
ProbeRsRejectsBothTransports verifies setting both usbip and remote is rejected.
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/flash/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
probe-rs-rejects-both-transportsfunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Probersrejectsbothtransports(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.probersrejectsbothtransports()
)@func()
async example(): Promise<void> {
return dag
.tests()
.probeRsRejectsBothTransports()
}probeRsRejectsNilFirmware() 🔗
ProbeRsRejectsNilFirmware verifies a nil firmware is rejected — either by the SDK binding’s assertNotNil panic or by ProbeRs’s own up-front check.
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/flash/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
probe-rs-rejects-nil-firmwarefunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Probersrejectsnilfirmware(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.probersrejectsnilfirmware()
)@func()
async example(): Promise<void> {
return dag
.tests()
.probeRsRejectsNilFirmware()
}probeRsRejectsNoTransport() 🔗
ProbeRsRejectsNoTransport verifies zero transports is rejected.
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/flash/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
probe-rs-rejects-no-transportfunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Probersrejectsnotransport(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.probersrejectsnotransport()
)@func()
async example(): Promise<void> {
return dag
.tests()
.probeRsRejectsNoTransport()
}probeRsRejectsUnknownChip() 🔗
ProbeRsRejectsUnknownChip verifies an unknown chip is rejected against probe-rs’s registry (this runs the real probe-rs binary).
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/flash/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
probe-rs-rejects-unknown-chipfunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Probersrejectsunknownchip(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.probersrejectsunknownchip()
)@func()
async example(): Promise<void> {
return dag
.tests()
.probeRsRejectsUnknownChip()
}probeRsRejectsUsbipWithoutBusid() 🔗
ProbeRsRejectsUsbipWithoutBusid verifies usbip without busid is rejected.
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/flash/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
probe-rs-rejects-usbip-without-busidfunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Probersrejectsusbipwithoutbusid(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.probersrejectsusbipwithoutbusid()
)@func()
async example(): Promise<void> {
return dag
.tests()
.probeRsRejectsUsbipWithoutBusid()
}runReExecutesNotCached() 🔗
RunReExecutesNotCached proves Run’s never-cache behavior by counting how many times two Run calls hit a fake-usbipd service. Each Run’s usbip attach opens one TCP connection; reading the counter before and after the two Runs, the Run-attributable connection delta must be exactly 2 (a cached Run would skip the connect and yield fewer).
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/flash/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
run-re-executes-not-cachedfunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Runreexecutesnotcached(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.runreexecutesnotcached()
)@func()
async example(): Promise<void> {
return dag
.tests()
.runReExecutesNotCached()
}runWithoutProbeFailsCleanly() 🔗
RunWithoutProbeFailsCleanly verifies that with no reachable probe, Run returns a non-zero exit code and captured output — NOT a Go error (the FlashResult failure contract). Points at the container’s own loopback where nothing listens, so probe-rs fails fast.
Return Type
Void ! Example
dagger -m github.com/z5labs/devex/daggerverse/flash/tests@a17bf411228ae3d544c7c18bcf08dd04c295d453 call \
run-without-probe-fails-cleanlyfunc (m *MyModule) Example(ctx context.Context) {
return dag.
Tests().
Runwithoutprobefailscleanly(ctx)
}@function
async def example() -> None:
return await (
dag.tests()
.runwithoutprobefailscleanly()
)@func()
async example(): Promise<void> {
return dag
.tests()
.runWithoutProbeFailsCleanly()
}