1
0
Fork 0
forked from wry/wry

autocommit 2022-05-01 21:44:09 CEST

This commit is contained in:
Julian Orth 2022-05-01 21:44:09 +02:00
parent cca3850800
commit 04580c4aeb
38 changed files with 815 additions and 124 deletions

View file

@ -12,7 +12,7 @@ use {
pub struct TestCallback {
pub id: WlCallbackId,
pub transport: Rc<TestTransport>,
pub tran: Rc<TestTransport>,
pub handler: Cell<Option<Box<dyn FnOnce()>>>,
pub done: Cell<bool>,
}

View file

@ -1,14 +1,38 @@
use {
crate::{
it::{test_object::TestObject, test_transport::TestTransport},
wire::WlCompositorId,
it::{
test_error::TestError, test_ifs::test_surface::TestSurface, test_object::TestObject,
test_transport::TestTransport,
},
wire::{wl_compositor::CreateSurface, WlCompositorId},
},
std::rc::Rc,
std::{cell::Cell, rc::Rc},
};
pub struct TestCompositor {
pub id: WlCompositorId,
pub transport: Rc<TestTransport>,
pub tran: Rc<TestTransport>,
}
impl TestCompositor {
pub async fn create_surface(&self) -> Result<Rc<TestSurface>, TestError> {
let id = self.tran.id();
self.tran.send(CreateSurface {
self_id: self.id,
id,
});
self.tran.sync().await;
let client = self.tran.get_client()?;
let server = client.lookup(id)?;
let surface = Rc::new(TestSurface {
id,
tran: self.tran.clone(),
server,
destroyed: Cell::new(false),
});
self.tran.add_obj(surface.clone())?;
Ok(surface)
}
}
test_object! {

View file

@ -12,7 +12,7 @@ use {
};
pub struct TestDisplay {
pub transport: Rc<TestTransport>,
pub tran: Rc<TestTransport>,
pub id: WlDisplayId,
}
@ -20,25 +20,25 @@ impl TestDisplay {
fn handle_error(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let ev = Error::parse_full(parser)?;
let msg = format!("Compositor sent an error: {}", ev.message);
self.transport.error(&msg);
self.transport.kill();
self.tran.error(&msg);
self.tran.kill();
Ok(())
}
fn handle_delete_id(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let ev = DeleteId::parse_full(parser)?;
match self.transport.objects.remove(&ObjectId::from_raw(ev.id)) {
match self.tran.objects.remove(&ObjectId::from_raw(ev.id)) {
None => {
let msg = format!(
"Compositor sent delete_id for object {} which does not exist",
ev.id
);
self.transport.error(&msg);
self.transport.kill();
self.tran.error(&msg);
self.tran.kill();
}
Some(obj) => {
obj.on_remove(&self.transport);
self.transport.obj_ids.borrow_mut().release(ev.id);
obj.on_remove(&self.tran);
self.tran.obj_ids.borrow_mut().release(ev.id);
}
}
Ok(())

View file

@ -2,12 +2,13 @@ use {
crate::{
client::ClientId,
it::{
test_error::TestError, test_object::TestObject, test_transport::TestTransport,
testrun::ParseFull,
test_error::TestError, test_ifs::test_screenshot::TestJayScreenshot,
test_object::TestObject, test_transport::TestTransport, testrun::ParseFull,
},
utils::buffd::MsgParser,
wire::{
jay_compositor::{self, *},
jay_screenshot::Dmabuf,
JayCompositorId,
},
},
@ -16,25 +17,44 @@ use {
pub struct TestJayCompositor {
pub id: JayCompositorId,
pub transport: Rc<TestTransport>,
pub tran: Rc<TestTransport>,
pub client_id: Cell<Option<ClientId>>,
}
impl TestJayCompositor {
pub async fn get_client_id(&self) -> Result<ClientId, TestError> {
if self.client_id.get().is_none() {
self.transport.send(GetClientId { self_id: self.id });
self.tran.send(GetClientId { self_id: self.id });
}
self.transport.sync().await;
self.tran.sync().await;
match self.client_id.get() {
Some(c) => Ok(c),
_ => bail!("Compositor did not send a client id"),
}
}
pub async fn take_screenshot(&self) -> Result<Dmabuf, TestError> {
let js = Rc::new(TestJayScreenshot {
id: self.tran.id(),
result: Cell::new(None),
});
self.tran.send(TakeScreenshot {
self_id: self.id,
id: js.id,
});
self.tran.add_obj(js.clone())?;
self.tran.sync().await;
match js.result.take() {
Some(Ok(res)) => Ok(res),
Some(Err(res)) => bail!("Compositor could not take a screenshot: {}", res),
None => bail!("Compositor did not send a screenshot"),
}
}
fn handle_client_id(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let ev = jay_compositor::ClientId::parse_full(parser)?;
self.client_id.set(Some(ClientId::from_raw(ev.client_id)));
self.tran.client_id.set(ClientId::from_raw(ev.client_id));
Ok(())
}
}

View file

@ -4,7 +4,7 @@ use {
test_error::TestError,
test_ifs::{
test_compositor::TestCompositor, test_jay_compositor::TestJayCompositor,
test_shm::TestShm,
test_shm::TestShm, test_xdg_base::TestXdgWmBase,
},
test_object::TestObject,
test_transport::TestTransport,
@ -26,16 +26,18 @@ pub struct TestRegistrySingletons {
pub jay_compositor: u32,
pub wl_compositor: u32,
pub wl_shm: u32,
pub xdg_wm_base: u32,
}
pub struct TestRegistry {
pub id: WlRegistryId,
pub transport: Rc<TestTransport>,
pub tran: Rc<TestTransport>,
pub globals: CopyHashMap<u32, Rc<TestGlobal>>,
pub singletons: CloneCell<Option<Rc<TestRegistrySingletons>>>,
pub jay_compositor: CloneCell<Option<Rc<TestJayCompositor>>>,
pub compositor: CloneCell<Option<Rc<TestCompositor>>>,
pub shm: CloneCell<Option<Rc<TestShm>>>,
pub xdg: CloneCell<Option<Rc<TestXdgWmBase>>>,
}
macro_rules! singleton {
@ -49,22 +51,22 @@ macro_rules! singleton {
impl TestRegistry {
pub async fn get_singletons(&self) -> Result<Rc<TestRegistrySingletons>, TestError> {
singleton!(self.singletons);
self.transport.sync().await;
self.tran.sync().await;
singleton!(self.singletons);
let mut jay_compositor = 0;
let mut wl_compositor = 0;
let mut wl_shm = 0;
for global in self.globals.lock().values() {
match global.interface.as_str() {
"jay_compositor" => jay_compositor = global.name,
"wl_compositor" => wl_compositor = global.name,
"wl_shm" => wl_shm = global.name,
_ => {}
}
}
macro_rules! singleton {
($($name:ident,)*) => {
TestRegistrySingletons {
($($name:ident,)*) => {{
$(
let mut $name = 0;
)*
for global in self.globals.lock().values() {
match global.interface.as_str() {
$(
stringify!($name) => $name = global.name,
)*
_ => {}
}
}
Rc::new(TestRegistrySingletons {
$(
$name: {
if $name == 0 {
@ -73,14 +75,15 @@ impl TestRegistry {
$name
},
)*
}
}
})
}}
}
let singletons = Rc::new(singleton! {
let singletons = singleton! {
jay_compositor,
wl_compositor,
wl_shm,
});
xdg_wm_base,
};
self.singletons.set(Some(singletons.clone()));
Ok(singletons)
}
@ -90,8 +93,8 @@ impl TestRegistry {
let singletons = self.get_singletons().await?;
singleton!(self.jay_compositor);
let jc = Rc::new(TestJayCompositor {
id: self.transport.id(),
transport: self.transport.clone(),
id: self.tran.id(),
tran: self.tran.clone(),
client_id: Default::default(),
});
self.bind(&jc, singletons.jay_compositor, 1)?;
@ -104,8 +107,8 @@ impl TestRegistry {
let singletons = self.get_singletons().await?;
singleton!(self.compositor);
let jc = Rc::new(TestCompositor {
id: self.transport.id(),
transport: self.transport.clone(),
id: self.tran.id(),
tran: self.tran.clone(),
});
self.bind(&jc, singletons.wl_compositor, 4)?;
self.compositor.set(Some(jc.clone()));
@ -117,8 +120,8 @@ impl TestRegistry {
let singletons = self.get_singletons().await?;
singleton!(self.shm);
let jc = Rc::new(TestShm {
id: self.transport.id(),
transport: self.transport.clone(),
id: self.tran.id(),
tran: self.tran.clone(),
formats: Default::default(),
formats_awaited: Cell::new(false),
});
@ -127,20 +130,34 @@ impl TestRegistry {
Ok(jc)
}
pub async fn get_xdg(&self) -> Result<Rc<TestXdgWmBase>, TestError> {
singleton!(self.xdg);
let singletons = self.get_singletons().await?;
singleton!(self.xdg);
let jc = Rc::new(TestXdgWmBase {
id: self.tran.id(),
tran: self.tran.clone(),
destroyed: Cell::new(false),
});
self.bind(&jc, singletons.xdg_wm_base, 3)?;
self.xdg.set(Some(jc.clone()));
Ok(jc)
}
pub fn bind<O: TestObject>(
&self,
obj: &Rc<O>,
name: u32,
version: u32,
) -> Result<(), TestError> {
self.transport.send(Bind {
self.tran.send(Bind {
self_id: self.id,
name,
interface: obj.interface().name(),
version,
id: obj.id().into(),
});
self.transport.add_obj(obj.clone())?;
self.tran.add_obj(obj.clone())?;
Ok(())
}
@ -155,7 +172,7 @@ impl TestRegistry {
}),
);
if prev.is_some() {
self.transport.error(&format!(
self.tran.error(&format!(
"Compositor sent global {} multiple times",
ev.name
));
@ -166,7 +183,7 @@ impl TestRegistry {
fn handle_global_remove(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let ev = GlobalRemove::parse_full(parser)?;
if self.globals.remove(&ev.name).is_none() {
self.transport.error(&format!(
self.tran.error(&format!(
"Compositor sent global_remove for {} which does not exist",
ev.name
));

View file

@ -0,0 +1,36 @@
use {
crate::{
it::{test_error::TestError, test_object::TestObject, testrun::ParseFull},
utils::buffd::MsgParser,
wire::{jay_screenshot::*, JayScreenshotId},
},
std::cell::Cell,
};
pub struct TestJayScreenshot {
pub id: JayScreenshotId,
pub result: Cell<Option<Result<Dmabuf, String>>>,
}
impl TestJayScreenshot {
fn handle_dmabuf(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let ev = Dmabuf::parse_full(parser)?;
self.result.set(Some(Ok(ev)));
Ok(())
}
fn handle_error(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let ev = Error::parse_full(parser)?;
self.result.set(Some(Err(ev.msg.to_string())));
Ok(())
}
}
test_object! {
TestJayScreenshot, JayScreenshot;
DMABUF => handle_dmabuf,
ERROR => handle_error,
}
impl TestObject for TestJayScreenshot {}

View file

@ -12,7 +12,7 @@ use {
pub struct TestShm {
pub id: WlShmId,
pub transport: Rc<TestTransport>,
pub tran: Rc<TestTransport>,
pub formats: CopyHashMap<u32, ()>,
pub formats_awaited: Cell<bool>,
}
@ -20,7 +20,7 @@ pub struct TestShm {
impl TestShm {
pub async fn formats(&self) -> &CopyHashMap<u32, ()> {
if !self.formats_awaited.replace(true) {
self.transport.sync().await;
self.tran.sync().await;
}
&self.formats
}
@ -28,18 +28,18 @@ impl TestShm {
pub fn create_pool(&self, size: usize) -> Result<Rc<TestShmPool>, TestError> {
let mem = TestMem::new(size)?;
let pool = Rc::new(TestShmPool {
id: self.transport.id(),
transport: self.transport.clone(),
id: self.tran.id(),
tran: self.tran.clone(),
mem: CloneCell::new(mem.clone()),
destroyed: Cell::new(false),
});
self.transport.send(CreatePool {
self.tran.send(CreatePool {
self_id: self.id,
id: pool.id,
fd: mem.fd.clone(),
size: size as _,
});
self.transport.add_obj(pool.clone())?;
self.tran.add_obj(pool.clone())?;
Ok(pool)
}

View file

@ -4,7 +4,8 @@ use {
test_error::TestError, test_mem::TestMem, test_object::TestObject,
test_transport::TestTransport, testrun::ParseFull,
},
utils::buffd::MsgParser,
theme::Color,
utils::{buffd::MsgParser, windows::WindowsExt},
wire::{wl_buffer::*, WlBufferId},
},
std::{
@ -16,7 +17,7 @@ use {
pub struct TestShmBuffer {
pub id: WlBufferId,
pub transport: Rc<TestTransport>,
pub tran: Rc<TestTransport>,
pub range: Range<usize>,
pub mem: Rc<TestMem>,
pub released: Cell<bool>,
@ -24,11 +25,21 @@ pub struct TestShmBuffer {
}
impl TestShmBuffer {
pub fn fill(&self, color: Color) {
let [cr, cg, cb, ca] = color.to_rgba_premultiplied();
for [b, g, r, a] in self.deref().array_chunks_ext::<4>() {
r.set(cr);
g.set(cg);
b.set(cb);
a.set(ca);
}
}
pub fn destroy(&self) {
if self.destroyed.replace(true) {
return;
}
self.transport.send(Destroy { self_id: self.id });
self.tran.send(Destroy { self_id: self.id });
}
fn handle_release(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {

View file

@ -13,7 +13,7 @@ use {
pub struct TestShmPool {
pub id: WlShmPoolId,
pub transport: Rc<TestTransport>,
pub tran: Rc<TestTransport>,
pub mem: CloneCell<Rc<TestMem>>,
pub destroyed: Cell<bool>,
}
@ -35,15 +35,15 @@ impl TestShmPool {
bail!("Out-of-bounds buffer");
}
let buffer = Rc::new(TestShmBuffer {
id: self.transport.id(),
transport: self.transport.clone(),
id: self.tran.id(),
tran: self.tran.clone(),
range: start..end,
mem,
released: Cell::new(true),
destroyed: Cell::new(false),
});
self.transport.add_obj(buffer.clone())?;
self.transport.send(CreateBuffer {
self.tran.add_obj(buffer.clone())?;
self.tran.send(CreateBuffer {
self_id: self.id,
id: buffer.id,
offset,
@ -58,7 +58,7 @@ impl TestShmPool {
pub fn resize(&self, size: usize) -> Result<(), TestError> {
let mem = self.mem.get().grow(size)?;
self.mem.set(mem);
self.transport.send(Resize {
self.tran.send(Resize {
self_id: self.id,
size: size as _,
});
@ -69,7 +69,7 @@ impl TestShmPool {
if self.destroyed.replace(true) {
return;
}
self.transport.send(Destroy { self_id: self.id });
self.tran.send(Destroy { self_id: self.id });
}
}

View file

@ -0,0 +1,65 @@
use {
crate::{
ifs::wl_surface::WlSurface,
it::{
test_error::TestError, test_object::TestObject, test_transport::TestTransport,
testrun::ParseFull,
},
utils::buffd::MsgParser,
wire::{wl_surface::*, WlBufferId, WlSurfaceId},
},
std::{cell::Cell, rc::Rc},
};
pub struct TestSurface {
pub id: WlSurfaceId,
pub tran: Rc<TestTransport>,
pub server: Rc<WlSurface>,
pub destroyed: Cell<bool>,
}
impl TestSurface {
pub fn destroy(&self) {
if !self.destroyed.replace(true) {
self.tran.send(Destroy { self_id: self.id });
}
}
pub fn attach(&self, buffer_id: WlBufferId) {
self.tran.send(Attach {
self_id: self.id,
buffer: buffer_id,
x: 0,
y: 0,
});
}
pub fn commit(&self) {
self.tran.send(Commit { self_id: self.id });
}
fn handle_enter(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let _ev = Enter::parse_full(parser)?;
Ok(())
}
fn handle_leave(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let _ev = Leave::parse_full(parser)?;
Ok(())
}
}
impl Drop for TestSurface {
fn drop(&mut self) {
self.destroy();
}
}
test_object! {
TestSurface, WlSurface;
ENTER => handle_enter,
LEAVE => handle_leave,
}
impl TestObject for TestSurface {}

View file

@ -0,0 +1,68 @@
use {
crate::{
it::{
test_error::TestError, test_ifs::test_xdg_surface::TestXdgSurface,
test_object::TestObject, test_transport::TestTransport, testrun::ParseFull,
},
utils::buffd::MsgParser,
wire::{xdg_wm_base::*, WlSurfaceId, XdgWmBaseId},
},
std::{cell::Cell, rc::Rc},
};
pub struct TestXdgWmBase {
pub id: XdgWmBaseId,
pub tran: Rc<TestTransport>,
pub destroyed: Cell<bool>,
}
impl TestXdgWmBase {
pub fn destroy(&self) {
if !self.destroyed.replace(true) {
self.tran.send(Destroy { self_id: self.id });
}
}
pub async fn create_xdg_surface(
&self,
surface: WlSurfaceId,
) -> Result<Rc<TestXdgSurface>, TestError> {
let id = self.tran.id();
self.tran.send(GetXdgSurface {
self_id: self.id,
id,
surface,
});
self.tran.sync().await;
let client = self.tran.get_client()?;
let server = client.lookup(id)?;
let xdg = Rc::new(TestXdgSurface {
id,
tran: self.tran.clone(),
server,
destroyed: Cell::new(false),
last_serial: Cell::new(0),
});
self.tran.add_obj(xdg.clone())?;
Ok(xdg)
}
fn handle_ping(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let _ev = Ping::parse_full(parser)?;
Ok(())
}
}
test_object! {
TestXdgWmBase, XdgWmBase;
PING => handle_ping,
}
impl TestObject for TestXdgWmBase {}
impl Drop for TestXdgWmBase {
fn drop(&mut self) {
self.destroy();
}
}

View file

@ -0,0 +1,78 @@
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,
},
utils::buffd::MsgParser,
wire::{xdg_surface::*, XdgSurfaceId},
},
std::{cell::Cell, rc::Rc},
};
pub struct TestXdgSurface {
pub id: XdgSurfaceId,
pub tran: Rc<TestTransport>,
pub server: Rc<XdgSurface>,
pub destroyed: Cell<bool>,
pub last_serial: Cell<u32>,
}
impl TestXdgSurface {
pub fn destroy(&self) {
if !self.destroyed.replace(true) {
self.tran.send(Destroy { self_id: self.id });
}
}
pub async fn create_toplevel(&self) -> Result<Rc<TestXdgToplevel>, TestError> {
let id = self.tran.id();
self.tran.send(GetToplevel {
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 {
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())?;
Ok(tl)
}
pub fn ack_configure(&self, serial: u32) {
self.tran.send(AckConfigure {
self_id: self.id,
serial,
});
}
fn handle_configure(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let ev = Configure::parse_full(parser)?;
self.last_serial.set(ev.serial);
Ok(())
}
}
impl Drop for TestXdgSurface {
fn drop(&mut self) {
self.destroy();
}
}
test_object! {
TestXdgSurface, XdgSurface;
CONFIGURE => handle_configure,
}
impl TestObject for TestXdgSurface {}

View file

@ -0,0 +1,72 @@
use {
crate::{
ifs::wl_surface::xdg_surface::xdg_toplevel::XdgToplevel,
it::{
test_error::TestError, test_object::TestObject, test_transport::TestTransport,
testrun::ParseFull,
},
utils::buffd::MsgParser,
wire::{xdg_toplevel::*, XdgToplevelId},
},
ahash::AHashSet,
std::{
cell::{Cell, RefCell},
rc::Rc,
},
};
pub struct TestXdgToplevel {
pub id: XdgToplevelId,
pub tran: Rc<TestTransport>,
pub destroyed: Cell<bool>,
pub server: Rc<XdgToplevel>,
pub width: Cell<i32>,
pub height: Cell<i32>,
pub states: RefCell<AHashSet<u32>>,
pub close_requested: Cell<bool>,
}
impl TestXdgToplevel {
pub fn destroy(&self) {
if !self.destroyed.replace(true) {
self.tran.send(Destroy { self_id: self.id });
}
}
fn handle_configure(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let ev = Configure::parse_full(parser)?;
self.width.set(ev.width);
self.height.set(ev.height);
*self.states.borrow_mut() = ev.states.iter().copied().collect();
Ok(())
}
fn handle_close(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let _ev = Close::parse_full(parser)?;
self.close_requested.set(true);
Ok(())
}
fn handle_configure_bounds(&self, parser: MsgParser<'_, '_>) -> Result<(), TestError> {
let _ev = ConfigureBounds::parse_full(parser)?;
Ok(())
}
}
impl Drop for TestXdgToplevel {
fn drop(&mut self) {
self.destroy();
}
}
test_object! {
TestXdgToplevel, XdgToplevel;
CONFIGURE => handle_configure,
CLOSE => handle_close,
CONFIGURE_BOUNDS => handle_configure_bounds,
}
impl TestObject for TestXdgToplevel {}