1
0
Fork 0
forked from wry/wry

it: test foreign-toplevel-list

This commit is contained in:
Julian Orth 2024-04-02 15:57:41 +02:00
parent 6fe6b1b491
commit a39031d4f9
12 changed files with 276 additions and 18 deletions

View file

@ -2,6 +2,8 @@ mod test_buffer;
pub mod test_callback;
pub mod test_compositor;
pub mod test_display;
pub mod test_ext_foreign_toplevel_handle;
pub mod test_ext_foreign_toplevel_list;
pub mod test_jay_compositor;
pub mod test_keyboard;
pub mod test_pointer;

View file

@ -1,5 +1,6 @@
use {
crate::{
client::MIN_SERVER_ID,
it::{
test_error::TestError, test_object::TestObject, test_transport::TestTransport,
testrun::ParseFull,
@ -36,7 +37,9 @@ impl TestDisplay {
}
Some(obj) => {
obj.on_remove(&self.tran);
self.tran.obj_ids.borrow_mut().release(ev.id);
if ev.id < MIN_SERVER_ID {
self.tran.obj_ids.borrow_mut().release(ev.id);
}
}
}
Ok(())

View file

@ -0,0 +1,74 @@
use {
crate::{
it::{
test_error::{TestError, TestResult},
test_object::TestObject,
test_transport::TestTransport,
testrun::ParseFull,
},
utils::buffd::MsgParser,
wire::{ext_foreign_toplevel_handle_v1::*, ExtForeignToplevelHandleV1Id},
},
std::{cell::Cell, rc::Rc},
};
pub struct TestExtForeignToplevelHandle {
pub id: ExtForeignToplevelHandleV1Id,
pub tran: Rc<TestTransport>,
pub destroyed: Cell<bool>,
pub closed: Cell<bool>,
pub title: Cell<Option<String>>,
pub app_id: Cell<Option<String>>,
pub identifier: Cell<Option<String>>,
}
impl TestExtForeignToplevelHandle {
fn destroy(&self) -> TestResult {
if !self.destroyed.replace(true) {
self.tran.send(Destroy { self_id: self.id })?;
}
Ok(())
}
fn handle_closed(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let _ev = Closed::parse_full(parser)?;
self.closed.set(true);
self.destroy()?;
Ok(())
}
fn handle_done(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let _ev = Done::parse_full(parser)?;
Ok(())
}
fn handle_title(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let ev = Title::parse_full(parser)?;
self.title.set(Some(ev.title.to_string()));
Ok(())
}
fn handle_app_id(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let ev = AppId::parse_full(parser)?;
self.app_id.set(Some(ev.app_id.to_string()));
Ok(())
}
fn handle_identifier(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let ev = Identifier::parse_full(parser)?;
self.identifier.set(Some(ev.identifier.to_string()));
Ok(())
}
}
test_object! {
TestExtForeignToplevelHandle, ExtForeignToplevelHandleV1;
CLOSED => handle_closed,
DONE => handle_done,
TITLE => handle_title,
APP_ID => handle_app_id,
IDENTIFIER => handle_identifier,
}
impl TestObject for TestExtForeignToplevelHandle {}

View file

@ -0,0 +1,70 @@
use {
crate::{
it::{
test_error::{TestError, TestResult},
test_ifs::test_ext_foreign_toplevel_handle::TestExtForeignToplevelHandle,
test_object::TestObject,
test_transport::TestTransport,
testrun::ParseFull,
},
utils::buffd::MsgParser,
wire::{ext_foreign_toplevel_list_v1::*, ExtForeignToplevelListV1Id},
},
std::{
cell::{Cell, RefCell},
rc::Rc,
},
};
pub struct TestExtForeignToplevelList {
pub id: ExtForeignToplevelListV1Id,
pub tran: Rc<TestTransport>,
pub destroyed: Cell<bool>,
pub toplevels: RefCell<Vec<Rc<TestExtForeignToplevelHandle>>>,
}
impl TestExtForeignToplevelList {
#[allow(dead_code)]
pub fn stop(&self) -> TestResult {
self.tran.send(Stop { self_id: self.id })?;
Ok(())
}
pub fn destroy(&self) -> TestResult {
if !self.destroyed.replace(true) {
self.tran.send(Destroy { self_id: self.id })?;
}
Ok(())
}
fn handle_toplevel(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let ev = Toplevel::parse_full(parser)?;
let tl = Rc::new(TestExtForeignToplevelHandle {
id: ev.toplevel,
tran: self.tran.clone(),
destroyed: Cell::new(false),
closed: Cell::new(false),
title: Cell::new(None),
app_id: Cell::new(None),
identifier: Cell::new(None),
});
self.tran.add_obj(tl.clone())?;
self.toplevels.borrow_mut().push(tl);
Ok(())
}
fn handle_finished(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let _ev = Finished::parse_full(parser)?;
self.destroy()?;
Ok(())
}
}
test_object! {
TestExtForeignToplevelList, ExtForeignToplevelListV1;
TOPLEVEL => handle_toplevel,
FINISHED => handle_finished,
}
impl TestObject for TestExtForeignToplevelList {}

View file

@ -2,8 +2,11 @@ use {
crate::{
client::ClientId,
it::{
test_error::TestError, test_ifs::test_screenshot::TestJayScreenshot,
test_object::TestObject, test_transport::TestTransport, testrun::ParseFull,
test_error::{TestError, TestResult},
test_ifs::test_screenshot::TestJayScreenshot,
test_object::TestObject,
test_transport::TestTransport,
testrun::ParseFull,
},
utils::{buffd::MsgParser, cell_ext::CellExt},
wire::{
@ -33,6 +36,11 @@ impl TestJayCompositor {
}
}
pub fn enable_symmetric_delete(&self) -> TestResult {
self.tran.send(EnableSymmetricDelete { self_id: self.id })?;
Ok(())
}
pub async fn take_screenshot(&self, include_cursor: bool) -> Result<Dmabuf, TestError> {
let js = Rc::new(TestJayScreenshot {
id: self.tran.id(),

View file

@ -5,8 +5,10 @@ use {
it::{
test_error::TestError,
test_ifs::{
test_compositor::TestCompositor, test_jay_compositor::TestJayCompositor,
test_shm::TestShm, test_single_pixel_buffer_manager::TestSinglePixelBufferManager,
test_compositor::TestCompositor,
test_ext_foreign_toplevel_list::TestExtForeignToplevelList,
test_jay_compositor::TestJayCompositor, test_shm::TestShm,
test_single_pixel_buffer_manager::TestSinglePixelBufferManager,
test_subcompositor::TestSubcompositor, test_viewporter::TestViewporter,
test_xdg_activation::TestXdgActivation, test_xdg_base::TestXdgWmBase,
},
@ -17,7 +19,10 @@ use {
utils::{buffd::MsgParser, clonecell::CloneCell, copyhashmap::CopyHashMap},
wire::{wl_registry::*, WlRegistryId, WlSeat},
},
std::{cell::Cell, rc::Rc},
std::{
cell::{Cell, RefCell},
rc::Rc,
},
};
pub struct TestGlobal {
@ -35,6 +40,7 @@ pub struct TestRegistrySingletons {
pub wp_single_pixel_buffer_manager_v1: u32,
pub wp_viewporter: u32,
pub xdg_activation_v1: u32,
pub ext_foreign_toplevel_list_v1: u32,
}
pub struct TestRegistry {
@ -50,6 +56,7 @@ pub struct TestRegistry {
pub viewporter: CloneCell<Option<Rc<TestViewporter>>>,
pub xdg: CloneCell<Option<Rc<TestXdgWmBase>>>,
pub activation: CloneCell<Option<Rc<TestXdgActivation>>>,
pub foreign_toplevel_list: CloneCell<Option<Rc<TestExtForeignToplevelList>>>,
pub seats: CopyHashMap<GlobalName, Rc<WlSeatGlobal>>,
}
@ -100,6 +107,7 @@ impl TestRegistry {
wp_single_pixel_buffer_manager_v1,
wp_viewporter,
xdg_activation_v1,
ext_foreign_toplevel_list_v1,
};
self.singletons.set(Some(singletons.clone()));
Ok(singletons)
@ -215,6 +223,23 @@ impl TestRegistry {
Ok(jc)
}
pub async fn get_foreign_toplevel_list(
&self,
) -> Result<Rc<TestExtForeignToplevelList>, TestError> {
singleton!(self.foreign_toplevel_list);
let singletons = self.get_singletons().await?;
singleton!(self.foreign_toplevel_list);
let jc = Rc::new(TestExtForeignToplevelList {
id: self.tran.id(),
tran: self.tran.clone(),
destroyed: Cell::new(false),
toplevels: RefCell::new(vec![]),
});
self.bind(&jc, singletons.ext_foreign_toplevel_list_v1, 1)?;
self.foreign_toplevel_list.set(Some(jc.clone()));
Ok(jc)
}
pub fn bind<O: TestObject>(
&self,
obj: &Rc<O>,

View file

@ -56,6 +56,14 @@ impl TestXdgToplevelCore {
Ok(())
}
pub fn set_title(&self, title: &str) -> Result<(), TestError> {
self.tran.send(SetTitle {
self_id: self.id,
title,
})?;
Ok(())
}
fn handle_configure(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let ev = Configure::parse_full(parser)?;
self.width.set(ev.width);

View file

@ -13,18 +13,20 @@ macro_rules! tassert {
macro_rules! tassert_eq {
($left:expr, $right:expr) => {{
let left = $left;
let right = $right;
if left != right {
bail!(
"Assert `{} = {:?} = {:?} = {}` failed ({}:{})",
stringify!($left),
left,
right,
stringify!($right),
file!(),
line!()
);
match ($left, $right) {
(left, right) => {
if left != right {
bail!(
"Assert `{} = {:?} = {:?} = {}` failed ({}:{})",
stringify!($left),
left,
right,
stringify!($right),
file!(),
line!()
);
}
}
}
}};
}

View file

@ -60,6 +60,7 @@ impl TestTransport {
viewporter: Default::default(),
xdg: Default::default(),
activation: Default::default(),
foreign_toplevel_list: Default::default(),
seats: Default::default(),
});
self.send(wl_display::GetRegistry {

View file

@ -74,6 +74,7 @@ impl TestRun {
tran.init();
let registry = tran.get_registry();
let jc = registry.get_jay_compositor().await?;
jc.enable_symmetric_delete()?;
let client_id = jc.get_client_id().await?;
let client = self.state.clients.get(client_id)?;
Ok(Rc::new(TestClient {

View file

@ -54,6 +54,7 @@ mod t0020_surface_offset;
mod t0021_preferred_buffer_scale;
mod t0022_toplevel_suspended;
mod t0023_xdg_activation;
mod t0024_foreign_toplevel_list;
pub trait TestCase: Sync {
fn name(&self) -> &'static str;
@ -96,5 +97,6 @@ pub fn tests() -> Vec<&'static dyn TestCase> {
t0021_preferred_buffer_scale,
t0022_toplevel_suspended,
t0023_xdg_activation,
t0024_foreign_toplevel_list,
}
}

View file

@ -0,0 +1,62 @@
use {
crate::{
it::{test_error::TestResult, testrun::TestRun},
wire::WlBufferId,
},
ahash::AHashSet,
std::rc::Rc,
};
testcase!();
async fn test(run: Rc<TestRun>) -> TestResult {
let _ds = run.create_default_setup().await?;
let client1 = run.create_client().await?;
let client2 = run.create_client().await?;
let list = client2.registry.get_foreign_toplevel_list().await?;
let win1 = client1.create_window().await?;
win1.tl.core.set_title("a")?;
win1.map().await?;
let win2 = client1.create_window().await?;
win2.tl.core.set_title("b")?;
win2.map().await?;
client2.sync().await;
let tls = list.toplevels.take();
tassert_eq!(tls.len(), 2);
tassert_eq!(tls[0].title.take().as_deref(), Some("a"));
tassert_eq!(tls[1].title.take().as_deref(), Some("b"));
let mut ids = AHashSet::new();
ids.insert(tls[0].identifier.take().unwrap());
ids.insert(tls[1].identifier.take().unwrap());
win2.tl.core.set_title("c")?;
client1.sync().await;
client2.sync().await;
tassert_eq!(tls[1].title.take().as_deref(), Some("c"));
win2.surface.attach(WlBufferId::NONE)?;
win2.surface.commit()?;
client1.sync().await;
client2.sync().await;
tassert!(tls[1].closed.get());
win2.map().await?;
client1.sync().await;
let tls = list.toplevels.take();
tassert_eq!(tls.len(), 1);
tassert_eq!(tls[0].title.take().as_deref(), Some("c"));
ids.insert(tls[0].identifier.take().unwrap());
tassert_eq!(ids.len(), 3);
Ok(())
}