本文へ移動
cccskills
無料GitHub で公開

qemu-system-test-runner

Author and run QEMU system emulation as an embedded-test target - qemu-system-arm / qemu-system-aarch64 / qemu-system-riscv32 launching cross-compiled ELF binaries on virtual MCUs and SoCs. Covers machine selection (-M virt / mps2-an385 / mps2-an386 / mps2-an500 / mps2-an511 / mps3-an524 / lm3s6965evb / raspi3b / xilinx-zynq-a9), CPU selection (-cpu cortex-m0 / cortex-m3 / cortex-m4 / cortex-m33 / cortex-a15 / cortex-a57 / max), -kernel ELF load, -nographic + -serial stdio, ARM semihosting via -semihosting-config enable=on,target=native (so cross-compiled GoogleTest / Unity binaries print to host stdio and exit with the test return code), GDB stub via -S -gdb tcp::1234, QMP monitor via -qmp tcp:host:port for automated test orchestration, and CI wiring. Use when host-only test runs are insufficient and the team wants arch-correct (endianness / alignment / interrupt-vector) behaviour on a virtual MCU without committing to physical hardware-in-loop.

日本語の概要は準備中です。原文の説明を表示しています。

testland/qaスター 13(GitHub 13 + cccskills 0)

実行スコア 未検証

インストール方法を見る

含まれるファイル(5)

  • SKILL.md11.2 KB
  • .tessl-plugin/plugin.json1.1 KB
  • references/boards.md1.8 KB
  • references/ci.md1.7 KB
  • references/flags.md968 B

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

qemu-system-test-runner

Overview

QEMU system emulation (per qemu.org system docs) runs cross-compiled ELF test binaries on virtual MCUs and SoCs. The embedded-relevant binaries are qemu-system-arm, qemu-system-aarch64, qemu-system-riscv32, and qemu-system-riscv64.

In an embedded test pipeline QEMU sits between the host build (fast, but misses arch-specific behaviour) and the physical hardware-in-loop rig (slow, expensive). A cross-compiled GoogleTest or Unity binary runs under QEMU with semihosting; the test's main() returns the failure count; QEMU exits with that code; CI gates on it.

Composes with:

  • googletest-embedded-arm - cross-compiled C++ test binary.
  • unity-test-framework-c - cross-compiled C test binary.
  • ceedling-build-runner - Ceedling project configured for ARM cross-compile.
  • hardware-in-loop-reference - the next rung up the V-cycle (PIL / HIL).

When to use

  • Host tests pass but you suspect arch-specific bugs (endianness, alignment, interrupt-vector ordering, weak-symbol resolution).
  • Physical HIL is expensive / scheduled - QEMU is the V-cycle PIL stage between SIL and HIL.
  • The team wants reproducible "on-target" tests in CI without flashing a real board.
  • Cross-compile target is one of QEMU's supported boards (Cortex-M3/M4/M7/M33 via mps2-* boards; Cortex-A* via virt / raspi / zynq; RISC-V via virt).

QEMU does not emulate analog I/O, sensor wiring, or real-time timing precisely - for that, escalate to a real HIL rig per hardware-in-loop-reference.

Authoring

Machine + CPU selection

Match the machine to the CPU profile: mps2-* boards for M-profile cores, virt for A-profile and RISC-V. The common Cortex-M mapping:

Test targetQEMU commandTypical -cpu
Cortex-M0 / M0+qemu-system-arm -M mps2-an385cortex-m0
Cortex-M3qemu-system-arm -M mps2-an385cortex-m3 (board default)
Cortex-M4qemu-system-arm -M mps2-an386cortex-m4

The full machine list, the A-profile / Raspberry Pi / Xilinx targets, and the max CPU note are in references/boards.md.

Booting the test ELF

For an embedded test, load the ELF with -kernel and send serial to the console with -nographic. The full invocation flag table (-M, -cpu, -smp, -m, -bios, -serial, -monitor, -qmp), per invocation.html, is in references/flags.md.

ARM semihosting

The critical flag for cross-compiled test binaries:

-semihosting-config [enable=on|off][,target=native|gdb|auto][,chardev=name][,arg=string]

Per the same invocation page, semihosting "allows direct host system calls and I/O operations". When the test ELF was linked with --specs=rdimon.specs, printf and exit() from the binary go through ARM semihosting calls; with -semihosting-config enable=on,target=native QEMU services those calls against the host.

Practically: the test binary's main() returns the failure count; the C runtime calls _exit(rc); QEMU exits with rc. CI gates on $?.

Building (the test binary side)

The test side is covered in googletest-embedded-arm and unity-test-framework-c; the canonical Cortex-M4 build:

arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -O0 -g \
    --specs=rdimon.specs \
    test/test_ringbuffer.c test/test_ringbuffer_Runner.c \
    src/ringbuffer.c ext/Unity/src/unity.c \
    -o build/test.elf -lrdimon

-lrdimon links the ARM semihosting library (developer.arm.com GNU Toolchain). --specs=rdimon.specs pulls in startup code that wires printf / _write / _exit to the semihosting interface.

Running

Smoke run

qemu-system-arm -M mps2-an386 -cpu cortex-m4 \
    -nographic \
    -semihosting-config enable=on,target=native \
    -kernel build/test.elf

Output (Unity-style):

test/test_ringbuffer.c:34:test_ringbuffer_initially_empty:PASS
test/test_ringbuffer.c:42:test_ringbuffer_push_increments_size:PASS

-----------------------
2 Tests 0 Failures 0 Ignored
OK

Exit code: 0 (or the failure count for Unity / GoogleTest).

Inspecting boot / interrupt behaviour

Per the invocation page, -d "activates debug logging for specified subsystems":

qemu-system-arm -M mps2-an386 -cpu cortex-m4 \
    -nographic -semihosting-config enable=on,target=native \
    -d int,cpu_reset,unimp \
    -kernel build/test.elf 2> qemu-debug.log

-d help lists the available items. int traces interrupts; cpu_reset traces resets; unimp traces unimplemented features (board-quirk hunts).

GDB-attached debug

# Terminal 1
qemu-system-arm -M mps2-an386 -cpu cortex-m4 -nographic \
    -semihosting-config enable=on,target=native \
    -S -gdb tcp::1234 \
    -kernel build/test.elf

# Terminal 2
arm-none-eabi-gdb build/test.elf \
    -ex "target remote :1234" \
    -ex "b main" \
    -ex "continue"

-S "freezes the CPU at startup"; -gdb tcp::1234 "opens a GDB stub on the specified device" (per the invocation page).

QMP for automated orchestration

Per the same invocation reference, -qmp tcp:host:port[,server, nowait] exposes the QEMU Machine Protocol over TCP as JSON-RPC. For a CI orchestration that needs to inject faults mid-test:

qemu-system-arm -M mps2-an386 -cpu cortex-m4 -nographic \
    -semihosting-config enable=on,target=native \
    -qmp tcp:localhost:4444,server,nowait \
    -kernel build/test.elf

A test harness then connects to localhost:4444 and issues {"execute":"query-status"}, {"execute":"stop"}, {"execute":"cont"} - useful for staged fault injection that mirrors the HIL fault-injection patterns.

Parsing results

Exit code (primary signal)

Semihosting's _exit(rc) propagates rc through QEMU. A test binary linked with --specs=rdimon.specs and ending in:

int main(void) {
    UNITY_BEGIN();
    RUN_TEST(test_x);
    return UNITY_END();   /* failure count */
}

…makes qemu-system-arm ... -kernel test.elf; echo $? return the failure count. CI gates on the exit code directly.

stdout parsing

For Unity / GoogleTest, the canonical line format reaches host stdout via semihosting → QEMU stdio. Grep / tee / pipe-to-JUnit the same way as a host run - see unity-test-framework-c and googletest-embedded-arm.

Timing the run

QEMU emulation is not real-time. For a test that asserts on wall-clock latency, the result is wrong - QEMU executes faster than physical hardware for compute-bound code and slower for I/O-heavy code. For real-time-sensitive tests, escalate to hardware-in-loop-reference.

CI integration

The canonical GitHub Actions pipeline (install toolchain, cross-build, run under two CPU profiles) is in references/ci.md. The "run under multiple CPUs" pattern is the cheap way to catch CPU-feature regressions - float vs no-float, ARMv6-M vs ARMv7-M.

Anti-patterns

Anti-patternWhy it failsFix
Forgetting -semihosting-config enable=on,target=nativeTest prints nothing; QEMU never exitsAlways set both -semihosting-config enable=on and target=native (or auto)
-kernel pointed at a stripped binaryQEMU loads but symbol info gone for debugKeep -g debug info; strip only the release binary
Asserting on wall-clock timing under QEMUQEMU is not real-timeMove timing assertions to HIL; QEMU asserts only logical correctness
Using -M virt for a Cortex-M testvirt is Cortex-A - wrong instruction setMatch machine to CPU profile (mps2-* for M-profile, virt for A-profile)
Not pinning the QEMU versionNewer QEMU may emulate differently; CI flakesPin qemu-system-arm version in the runner image
Skipping -cpu and relying on board defaultBoard defaults shift between QEMU versionsAlways specify -cpu explicitly
Reading -monitor stdio and -nographic together without -serial mon:stdioSerial and monitor share stdio; output garblesUse -monitor none -serial stdio for clean output
Running QEMU in CI without a sane timeoutA hung test ELF runs foreverWrap in timeout 60 qemu-system-arm ...

Limitations

  • Not real-time. Per the QEMU docs (system overview), emulation timing is not deterministic. Use only for logical correctness; HIL for timing.
  • Peripheral coverage varies by board. Per the ARM target page, mps2-* boards expose a specific set of peripherals (UART, timer, GPIO via PL061); custom MCU peripherals are not modelled. If the test exercises an STM32 USART, you must mock the peripheral or use a real board.
  • No analog I/O. No ADC, no DAC, no electrical-level fault injection. That's strictly HIL territory.
  • max CPU diverges from production. The max CPU is per the cpu-features page "available for comprehensive feature testing"; passing on max does not mean passing on the production part.
  • QMP is structured but not stable across major QEMU versions. Pin the QEMU version in CI if you script QMP.
  • Semihosting has security implications on real hardware. In production firmware never link --specs=rdimon.specs; the semihosting bkpt is a debug-only path.

References

Cited inline. Foundational documents:

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

コメント

ログインなしで書き込めます。使ってみた感想、質問、動かなかった環境などを気軽にどうぞ。

まだコメントはありません。最初のコメントを書いてみませんか。

送信するとすぐに公開されます。メールアドレスや電話番号などの個人情報は書かないでください。URL は 2 つまでです。

0 / 1000 文字

このフォームは reCAPTCHA で保護されており、Google のプライバシーポリシーと利用規約が適用されます。

同じリポジトリのスキル

Builds a CI gate that fails the build on **new** WCAG / a11y violations introduced by a PR while grandfathering pre-existing violations on a per-rule / per-page baseline. Aggregates verdicts from axe-core / pa11y / Lighthouse a11y / WAVE / IBM Equal Access scans. Use when a project has accumulated a11y debt and a strict "zero violations" gate would block every PR - the ratchet pattern lets the team ship while preventing regressions.

日本語の概要は準備中です。原文の説明を表示しています。

testland/qa132026年10月20日 更新

Workflow skill that builds an A/B-test validity checklist from an experiment proposal, walking the canonical design-correctness gates - pre-registered OEC/power/guardrails, randomization unit + SRM check, assignment integrity, telemetry, peeking discipline, novelty/primacy, post-experiment SRM re-check - into a per-experiment checklist + sign-off form. Use when launching, auditing, or governing an experiment. For pitfall mechanics (guardrails, peeking) see experiment-results-interpreter's references; to read an already-valid result use experiment-results-interpreter; for per-SDK harness tests use experiment-sdk-testing - this gates DESIGN, not SDK code.

日本語の概要は準備中です。原文の説明を表示しています。

testland/qa132026年10月20日 更新

The single install-flow skill: the reference contract for the PWA install flow (installability gate fields, `beforeinstallprompt` handshake, per-platform paths - Android WebAPK / iOS Share menu / Firefox no-op - and the `display-mode` post-install signal, in references/install-flow-reference.md) plus the build-an-X workflow that emits the Add-to-Home-Screen suite. Walks the four-stage timeline, emitting one test per gate cell per [web.dev/articles/install-criteria][install-criteria], the deferred-prompt → `prompt()` → `userChoice` chain per [web.dev/articles/customize-install][customize-install], the iOS Safari manual-metadata branch (`apple-touch-icon`) per [web.dev/learn/pwa/installation][learn-pwa], and the post-install `(display-mode: standalone)` MQ assertion. Output: a Playwright spec with per-stage cells plus a coverage matrix. Use when a PWA's manifest, icons, or install handler change, when install conversion drops at an unknown stage, or when triaging a flaky install assertion.

日本語の概要は準備中です。原文の説明を表示しています。

testland/qa132026年10月20日 更新

Build-an-X workflow that uses an LLM to map existing tests to spec sections - given a spec doc + the test suite, the LLM identifies which tests cover which sections, surfaces uncovered sections (gap), and recommends specific tests to add. Output is a coverage matrix per spec ID. Scope is mapping tests that already exist and naming the gaps, not authoring tests for new acceptance criteria. Use when a spec doc and a test suite both exist but nobody can say which requirements are actually covered - before a release sign-off, an audit, or a decision about where to spend the next round of test effort.

日本語の概要は準備中です。原文の説明を表示しています。

testland/qa132026年10月20日 更新

Generates tests from natural-language specs (acceptance criteria, user stories, requirements) using an LLM, with confidence scoring per test case (LLM self-assessment plus heuristics: assertion quality, naming, completeness), batching uncertain cases for human review, and integration with the team's existing test framework. Use when the user asks to generate unit tests from acceptance criteria, convert user stories to test cases, automate test creation from requirements, or augment a spec-driven test suite with AI-generated stubs that are then curated before merge.

日本語の概要は準備中です。原文の説明を表示しています。

testland/qa132026年10月20日 更新

Configures Allure Report (test-runner adapter install, `allure-results` directory wiring, `categories.json` for failure classification, `history-trend.json` retention via the copy-history-between-runs pattern), runs the Allure CLI to convert `allure-results` to a static HTML site, and uploads the report as a CI artifact. Use when the team needs richer test reporting than JUnit XML - step-level attachments, per-test history, retry tracking, and severity / epic / feature labeling across framework-agnostic adapters (pytest, Jest, JUnit, TestNG, NUnit, Mocha). As a rich static HTML report generator, it is the open-source alternative to the sunset ExtentReports (JVM/.NET per-test HTML narrative); for hosted cross-run flakiness analytics rather than a static per-run report use currents-integration.

日本語の概要は準備中です。原文の説明を表示しています。

testland/qa132026年10月20日 更新

testland のスキルをすべて見る

このスキルの問題を報告する