Skip to content

tests: virtual HID device test harness (Linux/Windows/macOS/libusb)#815

Draft
Youw wants to merge 2 commits into
masterfrom
virtual-device-tests
Draft

tests: virtual HID device test harness (Linux/Windows/macOS/libusb)#815
Youw wants to merge 2 commits into
masterfrom
virtual-device-tests

Conversation

@Youw
Copy link
Copy Markdown
Member

@Youw Youw commented Jun 7, 2026

Summary

Adds a small, reusable virtual HID device test harness so HIDAPI can be tested without physical hardware. Tests are written purely against the public HIDAPI API plus a backend-agnostic test_virtual_device interface, so the same test runs against every backend that ships a provider.

Devices expose pre-recorded scenarios: the test sends a Feature report whose first payload byte is a command, and the device replays the matching canned input report — keeping the test code 100% platform-neutral.

Intended as a foundation further tests can build on (e.g. the hid_read_interrupt test in #799 can rebase onto this harness).

What's here

  • src/tests/test_device_io.c — a simple open → write → exchange reports (Feature trigger / input read) → close smoke test.
  • Four virtual-device providers, each self-skipping (CTest code 77) when its device can't be created:
Platform / backend Provider Mechanism CI
Linux / hidraw test_virtual_device_uhid.c kernel /dev/uhid runs + passes every push (ubuntu-cmake)
Linux / libusb test_virtual_device_rawgadget.c /dev/raw-gadget + dummy_hcd, inside a VM runs + passes (manual libusb-vhid-test)
Windows / winapi test_virtual_device_win.c + windows/driver/ modified vhidmini2 UMDF2 driver runs + passes (manual win-vhid-test)
macOS / darwin test_virtual_device_mac.c IOHIDUserDevice (IOKit) builds + self-skips on hosted CI (runs on a real Mac)

See src/tests/README.md for details, including why FreeBSD/NetBSD/OpenBSD have no provider (no userspace HID/USB-create facility on any BSD).

CI

  • Per-push (builds.yml): the test is built on all platforms and run where possible. ubuntu-cmake loads uhid and runs DeviceIO_hidraw for real; Windows/macOS build the test and self-skip — so the matrix stays green everywhere.
  • win-vhid-test.yml (manual): builds, self-signs and installs the vhidmini2 driver on a hosted windows-latest runner and runs DeviceIO_winapi against the real device. ✅ verified passing.
  • libusb-vhid-test.yml (manual): the hosted ubuntu-latest (azure) kernel has no USB gadget subsystem, so this runs DeviceIO_libusb inside a lightweight virtme-ng + QEMU VM that boots a generic kernel (building dummy_hcd out-of-tree and loading raw_gadget), against a real virtual USB device. ✅ verified passing. The same approach works locally and on WSL2.

The two privileged jobs run only via workflow_dispatch or when a pull request carries the ci-virtual-device label, so they stay out of the per-push matrix.

Commits

  1. tests: add a backend-agnostic virtual HID device test harness
  2. ci: build and run the virtual HID device tests

Drafted with Claude Code.

@Youw Youw added the ci-virtual-device Run the virtual HID device CI jobs (Windows driver + libusb raw-gadget) label Jun 7, 2026
@mcuee
Copy link
Copy Markdown
Member

mcuee commented Jun 7, 2026

Great. We need this kind of virtual test device for hidapi (and also libusb).

@Youw Youw force-pushed the virtual-device-tests branch from 1cdc8d5 to b330600 Compare June 7, 2026 11:54
@mcuee
Copy link
Copy Markdown
Member

mcuee commented Jun 7, 2026

@Youw

FYI on WDK, the Windows runners have WDK installed already.

Nuget WDK -- smaller but lacking some tools, which may be okay for this purpose
Built-in WDK -- good enough
EWDK -- great for local build of libusb-win32/libusbK but not good for CI.

Reference:

@Youw Youw force-pushed the virtual-device-tests branch from b330600 to b4693d6 Compare June 7, 2026 12:03
Youw added 2 commits June 7, 2026 16:51
Add a reusable harness that runs HIDAPI tests against a *virtual* HID device,
needing no physical hardware. Tests use only the public HIDAPI API plus a
backend-agnostic test_virtual_device interface, so the same test runs against
every backend that ships a virtual-device provider. Devices expose pre-recorded
"scenarios": the test sends a Feature report carrying a command byte and the
device replays the matching canned input report.

- src/tests/test_device_io.c: a simple open -> write -> exchange reports ->
  close smoke test (skips via CTest code 77 when no virtual device is present).
- Providers:
    test_virtual_device_uhid.c       Linux hidraw  (kernel /dev/uhid)
    test_virtual_device_rawgadget.c  Linux libusb  (/dev/raw-gadget + dummy_hcd)
    test_virtual_device_win.c (+windows/driver/)   Windows winapi (vhidmini2 UMDF2)
    test_virtual_device_mac.c        macOS darwin  (IOHIDUserDevice)
  Each self-skips when its device can't be created.
- HIDAPI_WITH_TESTS is offered on Linux/macOS too; src/tests builds the test for
  whichever backend(s) are present.
- src/tests/README.md documents the providers, the scenario protocol, and why
  FreeBSD/NetBSD/OpenBSD have no provider (no userspace HID/USB-create facility).

Assisted-by: Claude:claude-opus-4.8
- builds.yml: build the test on Linux/Windows/macOS and run it where possible
  (ubuntu-cmake loads uhid and runs DeviceIO_hidraw; Windows/macOS/libusb build
  and self-skip), keeping the per-push matrix green.
- win-vhid-test.yml: build, self-sign and install the vhidmini2 driver on a
  hosted windows-latest runner and run DeviceIO_winapi against it.
- libusb-vhid-test.yml (+ .github/vmrun-libusb.sh): the hosted kernel has no USB
  gadget subsystem, so run DeviceIO_libusb inside a virtme-ng VM that boots a
  generic kernel (building dummy_hcd out-of-tree and loading raw_gadget) against
  a real virtual USB device.

Both privileged jobs run only via workflow_dispatch or a 'ci-virtual-device'
pull-request label, so they stay out of the per-push matrix.

Assisted-by: Claude:claude-opus-4.8
@Youw Youw force-pushed the virtual-device-tests branch from 5a24890 to 6089973 Compare June 7, 2026 13:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-virtual-device Run the virtual HID device CI jobs (Windows driver + libusb raw-gadget)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants