//! Integration coverage for client input-device classification helpers. //! //! Scope: include the input aggregator source and exercise private device //! classification against synthetic uinput keyboard/mouse devices. //! Targets: `client/src/input/inputs.rs`. //! Why: device classification regressions can silently break all input capture //! at runtime, so classifier behavior should stay under contract. mod layout { pub use lesavka_client::layout::*; } mod keyboard { pub use lesavka_client::input::keyboard::*; } mod mouse { pub use lesavka_client::input::mouse::*; } #[allow(warnings)] mod inputs_contract { include!(env!("LESAVKA_CLIENT_INPUTS_SRC")); use evdev::AttributeSet; use evdev::uinput::VirtualDevice; use serial_test::serial; use std::thread; fn open_virtual_device(vdev: &mut VirtualDevice) -> Option { for _ in 0..40 { if let Ok(mut nodes) = vdev.enumerate_dev_nodes_blocking() { if let Some(Ok(path)) = nodes.next() { if let Ok(dev) = evdev::Device::open(path) { let _ = dev.set_nonblocking(true); return Some(dev); } } } thread::sleep(std::time::Duration::from_millis(10)); } None } fn build_keyboard() -> Option { let mut keys = AttributeSet::::new(); keys.insert(evdev::KeyCode::KEY_A); keys.insert(evdev::KeyCode::KEY_ENTER); let mut vdev = VirtualDevice::builder() .ok()? .name("lesavka-input-classify-kbd") .with_keys(&keys) .ok()? .build() .ok()?; open_virtual_device(&mut vdev) } fn build_mouse() -> Option { let mut keys = AttributeSet::::new(); keys.insert(evdev::KeyCode::BTN_LEFT); let mut rel = AttributeSet::::new(); rel.insert(evdev::RelativeAxisCode::REL_X); rel.insert(evdev::RelativeAxisCode::REL_Y); let mut vdev = VirtualDevice::builder() .ok()? .name("lesavka-input-classify-mouse") .with_keys(&keys) .ok()? .with_relative_axes(&rel) .ok()? .build() .ok()?; open_virtual_device(&mut vdev) } #[test] #[serial] fn classify_device_recognizes_keyboard_and_mouse_capabilities() { if let Some(kbd) = build_keyboard() { assert!(matches!(classify_device(&kbd), DeviceKind::Keyboard)); } if let Some(mouse) = build_mouse() { assert!(matches!(classify_device(&mouse), DeviceKind::Mouse)); } } }