From 91022cd1c8965ca808a8d8bc2e276862c32057e9 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Tue, 2 Apr 2024 14:30:24 +0200 Subject: [PATCH] it: test suspended state --- .../wl_surface/xdg_surface/xdg_toplevel.rs | 2 +- src/it.rs | 10 ++-- src/it/test_client.rs | 1 + src/it/test_ifs/test_registry.rs | 2 +- src/it/test_ifs/test_xdg_surface.rs | 19 ++++---- src/it/test_ifs/test_xdg_toplevel.rs | 36 +++++++++----- src/it/test_utils/test_ouput_node_ext.rs | 15 +++++- src/it/test_utils/test_window.rs | 2 +- src/it/tests.rs | 7 +++ src/it/tests/t0002_window.rs | 8 ++-- src/it/tests/t0014_container_scroll_focus.rs | 2 +- src/it/tests/t0022_toplevel_suspended.rs | 48 +++++++++++++++++++ 12 files changed, 119 insertions(+), 33 deletions(-) create mode 100644 src/it/tests/t0022_toplevel_suspended.rs diff --git a/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs b/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs index f77943ba..f8909b09 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs @@ -64,7 +64,7 @@ const STATE_TILED_LEFT: u32 = 5; const STATE_TILED_RIGHT: u32 = 6; const STATE_TILED_TOP: u32 = 7; const STATE_TILED_BOTTOM: u32 = 8; -const STATE_SUSPENDED: u32 = 9; +pub const STATE_SUSPENDED: u32 = 9; #[allow(dead_code)] const CAP_WINDOW_MENU: u32 = 1; diff --git a/src/it.rs b/src/it.rs index f77d8285..d1b93262 100644 --- a/src/it.rs +++ b/src/it.rs @@ -42,6 +42,10 @@ mod tests; const SINGLE_THREAD: bool = false; pub fn run_tests() { + run_tests_(tests::tests()); +} + +fn run_tests_(tests: Vec<&'static dyn TestCase>) { leaks::init(); test_logger::install(); test_logger::set_level(Level::Trace); @@ -54,13 +58,13 @@ pub fn run_tests() { failed: Default::default(), }); if SINGLE_THREAD { - for test in tests::tests() { + for test in tests { with_test_config(|cfg| { run_test(&it_run, test, cfg); }) } } else { - let queue = Arc::new(Mutex::new(VecDeque::from_iter(tests::tests()))); + let queue = Arc::new(Mutex::new(VecDeque::from_iter(tests))); let mut threads = vec![]; let num_cpus = match num_cpus() { Ok(n) => n, @@ -139,7 +143,7 @@ fn run_test(it_run: &ItRun, test: &'static dyn TestCase, cfg: Rc) { Box::new(async move { let future: Pin<_> = test.run(testrun.clone()).into(); let future = state.eng.spawn2(Phase::Present, future); - let timeout = state.wheel.timeout(5000); + let timeout = state.wheel.timeout(500000); match future::select(future, timeout).await { Either::Left((Ok(..), _)) => {} Either::Left((Err(e), _)) => { diff --git a/src/it/test_client.rs b/src/it/test_client.rs index 3f8b5e46..323f6db5 100644 --- a/src/it/test_client.rs +++ b/src/it/test_client.rs @@ -81,6 +81,7 @@ impl TestClient { } pub async fn sync(&self) { + self.run.state.eng.yield_now().await; self.run.sync().await; self.tran.sync().await; } diff --git a/src/it/test_ifs/test_registry.rs b/src/it/test_ifs/test_registry.rs index 5f31a73a..75b0d813 100644 --- a/src/it/test_ifs/test_registry.rs +++ b/src/it/test_ifs/test_registry.rs @@ -193,7 +193,7 @@ impl TestRegistry { tran: self.tran.clone(), destroyed: Cell::new(false), }); - self.bind(&jc, singletons.xdg_wm_base, 3)?; + self.bind(&jc, singletons.xdg_wm_base, 6)?; self.xdg.set(Some(jc.clone())); Ok(jc) } diff --git a/src/it/test_ifs/test_xdg_surface.rs b/src/it/test_ifs/test_xdg_surface.rs index 17c2d6e7..6ba3bdcb 100644 --- a/src/it/test_ifs/test_xdg_surface.rs +++ b/src/it/test_ifs/test_xdg_surface.rs @@ -2,8 +2,11 @@ use { crate::{ ifs::wl_surface::xdg_surface::XdgSurface, it::{ - test_error::TestError, test_ifs::test_xdg_toplevel::TestXdgToplevel, - test_object::TestObject, test_transport::TestTransport, testrun::ParseFull, + test_error::TestError, + test_ifs::test_xdg_toplevel::{TestXdgToplevel, TestXdgToplevelCore}, + test_object::TestObject, + test_transport::TestTransport, + testrun::ParseFull, }, utils::buffd::MsgParser, wire::{xdg_surface::*, XdgSurfaceId}, @@ -33,20 +36,20 @@ impl TestXdgSurface { self_id: self.id, id, })?; - self.tran.sync().await; - let client = self.tran.get_client()?; - let server = client.lookup(id)?; - let tl = Rc::new(TestXdgToplevel { + let core = Rc::new(TestXdgToplevelCore { id, tran: self.tran.clone(), destroyed: Cell::new(false), - server, width: Cell::new(0), height: Cell::new(0), states: Default::default(), close_requested: Cell::new(false), }); - self.tran.add_obj(tl.clone())?; + self.tran.add_obj(core.clone())?; + self.tran.sync().await; + let client = self.tran.get_client()?; + let server = client.lookup(id)?; + let tl = Rc::new(TestXdgToplevel { core, server }); Ok(tl) } diff --git a/src/it/test_ifs/test_xdg_toplevel.rs b/src/it/test_ifs/test_xdg_toplevel.rs index 5ea32b13..a921d4e7 100644 --- a/src/it/test_ifs/test_xdg_toplevel.rs +++ b/src/it/test_ifs/test_xdg_toplevel.rs @@ -18,11 +18,10 @@ use { }, }; -pub struct TestXdgToplevel { +pub struct TestXdgToplevelCore { pub id: XdgToplevelId, pub tran: Rc, pub destroyed: Cell, - pub server: Rc, pub width: Cell, pub height: Cell, @@ -31,14 +30,12 @@ pub struct TestXdgToplevel { pub close_requested: Cell, } -impl TestXdgToplevel { - pub fn destroy(&self) -> Result<(), TestError> { - if !self.destroyed.replace(true) { - self.tran.send(Destroy { self_id: self.id })?; - } - Ok(()) - } +pub struct TestXdgToplevel { + pub core: Rc, + pub server: Rc, +} +impl TestXdgToplevel { pub fn container_parent(&self) -> TestResult> { let parent = match self.server.tl_data().parent.get() { Some(p) => p, @@ -49,6 +46,15 @@ impl TestXdgToplevel { _ => bail!("toplevel parent is not a container"), } } +} + +impl TestXdgToplevelCore { + pub fn destroy(&self) -> Result<(), TestError> { + if !self.destroyed.replace(true) { + self.tran.send(Destroy { self_id: self.id })?; + } + Ok(()) + } fn handle_configure(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> { let ev = Configure::parse_full(parser)?; @@ -68,20 +74,26 @@ impl TestXdgToplevel { let _ev = ConfigureBounds::parse_full(parser)?; Ok(()) } + + fn handle_wm_capabilities(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> { + let _ev = WmCapabilities::parse_full(parser)?; + Ok(()) + } } -impl Drop for TestXdgToplevel { +impl Drop for TestXdgToplevelCore { fn drop(&mut self) { let _ = self.destroy(); } } test_object! { - TestXdgToplevel, XdgToplevel; + TestXdgToplevelCore, XdgToplevel; CONFIGURE => handle_configure, CLOSE => handle_close, CONFIGURE_BOUNDS => handle_configure_bounds, + WM_CAPABILITIES => handle_wm_capabilities, } -impl TestObject for TestXdgToplevel {} +impl TestObject for TestXdgToplevelCore {} diff --git a/src/it/test_utils/test_ouput_node_ext.rs b/src/it/test_utils/test_ouput_node_ext.rs index 472b4f98..f4e22847 100644 --- a/src/it/test_utils/test_ouput_node_ext.rs +++ b/src/it/test_utils/test_ouput_node_ext.rs @@ -1,13 +1,20 @@ use { crate::{ - it::test_error::TestResult, - tree::{OutputNode, WorkspaceNode}, + it::{ + test_error::TestResult, + test_utils::{ + test_container_node_ext::TestContainerExt, + test_workspace_node_ext::TestWorkspaceNodeExt, + }, + }, + tree::{OutputNode, ToplevelNode, WorkspaceNode}, }, std::rc::Rc, }; pub trait TestOutputNodeExt { fn workspace(&self) -> TestResult>; + fn first_toplevel(&self) -> TestResult>; } impl TestOutputNodeExt for OutputNode { @@ -17,4 +24,8 @@ impl TestOutputNodeExt for OutputNode { Some(w) => Ok(w), } } + + fn first_toplevel(&self) -> TestResult> { + self.workspace()?.container()?.first_toplevel() + } } diff --git a/src/it/test_utils/test_window.rs b/src/it/test_utils/test_window.rs index 20abd167..2363f78a 100644 --- a/src/it/test_utils/test_window.rs +++ b/src/it/test_utils/test_window.rs @@ -28,7 +28,7 @@ impl TestWindow { self.surface.attach(buffer.id)?; self.viewport.set_source(0, 0, 1, 1)?; self.viewport - .set_destination(self.tl.width.get(), self.tl.height.get())?; + .set_destination(self.tl.core.width.get(), self.tl.core.height.get())?; self.xdg.ack_configure(self.xdg.last_serial.get())?; self.surface.commit()?; self.surface.tran.sync().await; diff --git a/src/it/tests.rs b/src/it/tests.rs index c1e85851..375fe9f5 100644 --- a/src/it/tests.rs +++ b/src/it/tests.rs @@ -23,6 +23,11 @@ macro_rules! testcase { Box::new(test(testrun)) } } + + #[test] + fn single() { + crate::it::run_tests_(vec![&Test]) + } }; } @@ -47,6 +52,7 @@ mod t0018_click_to_active_ws; mod t0019_natural_scrolling; mod t0020_surface_offset; mod t0021_preferred_buffer_scale; +mod t0022_toplevel_suspended; pub trait TestCase: Sync { fn name(&self) -> &'static str; @@ -87,5 +93,6 @@ pub fn tests() -> Vec<&'static dyn TestCase> { t0019_natural_scrolling, t0020_surface_offset, t0021_preferred_buffer_scale, + t0022_toplevel_suspended, } } diff --git a/src/it/tests/t0002_window.rs b/src/it/tests/t0002_window.rs index 00f18237..f0b1c343 100644 --- a/src/it/tests/t0002_window.rs +++ b/src/it/tests/t0002_window.rs @@ -18,9 +18,9 @@ async fn test(run: Rc) -> Result<(), TestError> { let window = client.create_window().await?; window.map().await?; - tassert_eq!(window.tl.width.get(), 800); + tassert_eq!(window.tl.core.width.get(), 800); tassert_eq!( - window.tl.height.get(), + window.tl.core.height.get(), 600 - 2 * (run.state.theme.sizes.title_height.get() + 1) ); @@ -29,8 +29,8 @@ async fn test(run: Rc) -> Result<(), TestError> { Rect::new_sized( 0, 2 * (run.state.theme.sizes.title_height.get() + 1), - window.tl.width.get(), - window.tl.height.get(), + window.tl.core.width.get(), + window.tl.core.height.get(), ) .unwrap() ); diff --git a/src/it/tests/t0014_container_scroll_focus.rs b/src/it/tests/t0014_container_scroll_focus.rs index 4c9ffcb2..0186cbaf 100644 --- a/src/it/tests/t0014_container_scroll_focus.rs +++ b/src/it/tests/t0014_container_scroll_focus.rs @@ -35,7 +35,7 @@ async fn test(run: Rc) -> TestResult { // | w_tiled | [ w_mono1 | w_mono2 ] | with w_mono2 visible and active client.sync().await; - tassert_eq!(w_tiled.tl.width.get(), w_mono2.tl.width.get()); + tassert_eq!(w_tiled.tl.core.width.get(), w_mono2.tl.core.width.get()); let enters = dss.kb.enter.expect()?; diff --git a/src/it/tests/t0022_toplevel_suspended.rs b/src/it/tests/t0022_toplevel_suspended.rs new file mode 100644 index 00000000..328524da --- /dev/null +++ b/src/it/tests/t0022_toplevel_suspended.rs @@ -0,0 +1,48 @@ +use { + crate::{ + ifs::wl_surface::xdg_surface::xdg_toplevel::STATE_SUSPENDED, + it::{ + test_error::TestResult, + test_utils::{ + test_ouput_node_ext::TestOutputNodeExt, test_toplevel_node_ext::TestToplevelNodeExt, + }, + testrun::TestRun, + }, + }, + isnt::std_1::collections::IsntHashSet2Ext, + std::rc::Rc, +}; + +testcase!(); + +async fn test(run: Rc) -> TestResult { + let ds = run.create_default_setup().await?; + + let client = run.create_client().await?; + + let win1 = client.create_window().await?; + win1.set_color(255, 0, 0, 255); + win1.map2().await?; + + let win2 = client.create_window().await?; + win2.set_color(0, 255, 0, 255); + win2.map2().await?; + + let (x, y) = ds.output.first_toplevel()?.center(); + ds.move_to(x, y); + + tassert!(win2.tl.core.states.borrow().not_contains(&STATE_SUSPENDED)); + + client.sync().await; + run.cfg.set_mono(ds.seat.id(), true)?; + + client.sync().await; + tassert!(win2.tl.core.states.borrow().contains(&STATE_SUSPENDED)); + + run.cfg.set_mono(ds.seat.id(), false)?; + + client.sync().await; + tassert!(win2.tl.core.states.borrow().not_contains(&STATE_SUSPENDED)); + + Ok(()) +}