본문으로 건너뛰기
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 / 1,000자

이 양식은 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의 스킬 모두 보기

이 스킬의 문제 신고