Files
wl-webrtc/tests/integration_test.rs
dailz 6d49222de8 feat: Phase 1 MVP with audit fixes — Wayland screen capture + VAAPI encoding
Phase 1 MVP implementation of wl-webrtc: Wayland screen capture tool
with hardware-accelerated VAAPI H.264 encoding and WebTransport output.

Includes all 9 runtime bug fixes from code audit (fix-audit-issues plan):

CRITICAL:
- C2: h264_metadata BSF with repeat_sps/repeat_pps in encode pipeline
- C4: FpsLimit wired as timing gate in on_copy_complete

HIGH:
- C3+A2: DRM device discovery via dmabuf feedback MainDevice event,
  unified resolve_drm_path() helper (CLI > compositor > auto > fallback)
- H2: Separate physical_size (mm) from mode_size (pixels) in wl_output
- H1+A3: Multi-output warning + named-output-not-found error

MEDIUM:
- M5: tv_sec u32->u64 to avoid Y2106 timestamp truncation
- M4: Guard against SHM Buffer event (DMA-BUF only)

Key components:
- src/avhw.rs: FFmpeg VAAPI encoder + filter graph + BSF pipeline
- src/state.rs: Wayland event loop + output negotiation + screencopy
- src/cap_wlr_screencopy.rs: wlr-screencopy capture source
- src/fps_limit.rs: Frame rate limiting with configurable target
- src/transform.rs: Frame format conversion utilities
2026-04-05 23:35:00 +08:00

104 lines
3.0 KiB
Rust

use std::process::Command;
/// Helper: get the binary path. Uses the release build if available.
fn bin_path() -> &'static str {
"target/release/wl-webrtc"
}
#[test]
fn test_help_flag() {
let output = Command::new(bin_path())
.arg("--help")
.output()
.expect("failed to execute wl-webrtc --help");
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(output.status.success(), "--help should exit 0");
assert!(
stdout.contains("output"),
"help output should mention 'output'"
);
assert!(stdout.contains("fps"), "help output should mention 'fps'");
assert!(
stdout.contains("codec"),
"help output should mention 'codec'"
);
assert!(
stdout.contains("bitrate"),
"help output should mention 'bitrate'"
);
assert!(
stdout.contains("gop-size"),
"help output should mention 'gop-size'"
);
assert!(
stdout.contains("drm-device"),
"help output should mention 'drm-device'"
);
}
#[test]
fn test_rejects_invalid_args() {
let output = Command::new(bin_path())
.arg("--nonexistent-flag-xyz")
.output()
.expect("failed to execute wl-webrtc with invalid args");
assert!(
!output.status.success(),
"should reject unrecognized flag"
);
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.to_lowercase().contains("error")
|| stderr.to_lowercase().contains("unexpected")
|| stderr.to_lowercase().contains("unrecognized"),
"stderr should mention the error, got: {stderr}"
);
}
#[test]
fn test_rejects_hevc_codec() {
let output = Command::new(bin_path())
.arg("--output")
.arg("/dev/null")
.arg("--codec")
.arg("hevc")
.output()
.expect("failed to execute wl-webrtc --codec hevc");
// MVP only supports h264; hevc should be rejected.
assert!(
!output.status.success(),
"should reject hevc codec in MVP"
);
}
/// Tests requiring a live Wayland compositor and VAAPI hardware.
/// Run with: cargo test -- --ignored
#[test]
#[ignore]
fn test_capture_starts_with_valid_output() {
// This test requires:
// - A running Wayland compositor
// - VAAPI-compatible GPU hardware
// - A writable output path
let output = Command::new(bin_path())
.arg("--output")
.arg("/tmp/wl-webrtc-test-capture.mp4")
.arg("--fps")
.arg("10")
.output()
.expect("failed to start wl-webrtc");
// If we get here, the process ran and exited.
// In a real test, we'd give it time to capture a few frames
// and then send SIGINT, but for now just check it didn't
// immediately fail with an argument error.
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
!stderr.contains("error: unexpected") && !stderr.contains("error: invalid"),
"should not have argument parsing errors, got: {stderr}"
);
}