From 3abc83f9ed9ef36e17f888e99390b3c1b44bd12a Mon Sep 17 00:00:00 2001 From: Marco Allegretti Date: Wed, 11 Mar 2026 08:12:11 +0100 Subject: [PATCH] test(compositor): add protocol unit tests and stale identifier rejection Stale identifier rejection (state.rs): - WeftShellWindowData gains a closed: AtomicBool field (default false). - Dispatch::request() checks the closed flag before processing any request; posts a DefunctWindow error (code 0) if the window has been closed, satisfying the error enum defined in the protocol XML. Unit tests (protocols/mod.rs, 5 tests): - window_data_stores_fields: verifies app_id, title, role, and initial closed state are stored correctly. - closed_flag_transition: verifies AtomicBool store/load round-trip. - manager_interface_name_and_version: confirms generated interface name zweft_shell_manager_v1 and version 1. - window_interface_name_and_version: confirms generated interface name zweft_shell_window_v1 and version 1. - defunct_window_error_code: confirms Error::DefunctWindow == 0 as declared in the protocol XML. Also adds scripts/wsl-test.sh for running cargo test with the libdisplay-info shim in place. --- crates/weft-compositor/src/protocols/mod.rs | 56 +++++++++++++++++++++ crates/weft-compositor/src/state.rs | 12 ++++- scripts/wsl-test.sh | 29 +++++++++++ 3 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 scripts/wsl-test.sh diff --git a/crates/weft-compositor/src/protocols/mod.rs b/crates/weft-compositor/src/protocols/mod.rs index 4394037..860015a 100644 --- a/crates/weft-compositor/src/protocols/mod.rs +++ b/crates/weft-compositor/src/protocols/mod.rs @@ -28,6 +28,7 @@ pub struct WeftShellWindowData { pub app_id: String, pub title: String, pub role: String, + pub closed: std::sync::atomic::AtomicBool, } impl WeftShellState { @@ -40,3 +41,58 @@ impl WeftShellState { Self { _global: global } } } + +#[cfg(test)] +mod tests { + use std::sync::atomic::Ordering; + use wayland_server::Resource; + + use super::*; + + #[test] + fn window_data_stores_fields() { + let d = WeftShellWindowData { + app_id: "com.example.test".into(), + title: "Test Window".into(), + role: "normal".into(), + closed: std::sync::atomic::AtomicBool::new(false), + }; + assert_eq!(d.app_id, "com.example.test"); + assert_eq!(d.title, "Test Window"); + assert_eq!(d.role, "normal"); + assert!(!d.closed.load(Ordering::Relaxed)); + } + + #[test] + fn closed_flag_transition() { + let d = WeftShellWindowData { + app_id: String::new(), + title: String::new(), + role: String::new(), + closed: std::sync::atomic::AtomicBool::new(false), + }; + assert!(!d.closed.load(Ordering::Relaxed)); + d.closed.store(true, Ordering::Relaxed); + assert!(d.closed.load(Ordering::Relaxed)); + } + + #[test] + fn manager_interface_name_and_version() { + let iface = ZweftShellManagerV1::interface(); + assert_eq!(iface.name, "zweft_shell_manager_v1"); + assert_eq!(iface.version, 1); + } + + #[test] + fn window_interface_name_and_version() { + let iface = ZweftShellWindowV1::interface(); + assert_eq!(iface.name, "zweft_shell_window_v1"); + assert_eq!(iface.version, 1); + } + + #[test] + fn defunct_window_error_code() { + let code = server::zweft_shell_window_v1::Error::DefunctWindow as u32; + assert_eq!(code, 0); + } +} diff --git a/crates/weft-compositor/src/state.rs b/crates/weft-compositor/src/state.rs index 2a735e8..5adaa77 100644 --- a/crates/weft-compositor/src/state.rs +++ b/crates/weft-compositor/src/state.rs @@ -19,7 +19,7 @@ use smithay::{ reexports::{ calloop::{LoopHandle, LoopSignal}, wayland_server::{ - Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, + Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource, backend::{ClientData, ClientId, DisconnectReason}, protocol::{wl_buffer::WlBuffer, wl_output::WlOutput, wl_surface::WlSurface}, }, @@ -457,6 +457,7 @@ impl Dispatch for WeftCompositorState { app_id, title, role, + closed: std::sync::atomic::AtomicBool::new(false), }, ); window.configure(x, y, width, height, 0); @@ -471,10 +472,17 @@ impl Dispatch for WeftCompositorState { _client: &Client, resource: &ZweftShellWindowV1, request: zweft_shell_window_v1::Request, - _data: &WeftShellWindowData, + data: &WeftShellWindowData, _dh: &DisplayHandle, _data_init: &mut DataInit<'_, Self>, ) { + if data.closed.load(std::sync::atomic::Ordering::Relaxed) { + resource.post_error( + crate::protocols::server::zweft_shell_window_v1::Error::DefunctWindow as u32, + "request on closed window", + ); + return; + } match request { zweft_shell_window_v1::Request::Destroy => {} zweft_shell_window_v1::Request::UpdateMetadata { title, role } => { diff --git a/scripts/wsl-test.sh b/scripts/wsl-test.sh new file mode 100644 index 0000000..d802cfa --- /dev/null +++ b/scripts/wsl-test.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +set -e + +PROJECT="/mnt/c/Users/might/Desktop/Development/Systems/WEFT OS" + +FAKE_PC_DIR="$HOME/.local/fake-pkgconfig" +mkdir -p "$FAKE_PC_DIR" +cat > "$FAKE_PC_DIR/libdisplay-info.pc" << 'EOF' +prefix=/usr +exec_prefix=${prefix} +libdir=/usr/lib64 +includedir=/usr/include + +Name: libdisplay-info +Description: EDID and DisplayID library (version shim for cargo check) +Version: 0.2.9 +Libs: -L${libdir} -ldisplay-info +Cflags: -I${includedir} +EOF + +source "$HOME/.cargo/env" +export PKG_CONFIG_PATH="$FAKE_PC_DIR:/usr/lib64/pkgconfig:/usr/share/pkgconfig" + +cd "$PROJECT" + +echo "==> cargo test -p weft-compositor" +cargo test -p weft-compositor 2>&1 +echo "" +echo "ALL DONE"