Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

237
vendor/x11rb/tests/multithread_test.rs vendored Normal file
View File

@@ -0,0 +1,237 @@
use std::sync::Arc;
use x11rb::connection::Connection as _;
use x11rb::protocol::xproto::{
ClientMessageEvent, ConnectionExt as _, EventMask, CLIENT_MESSAGE_EVENT,
};
// Regression test for https://github.com/psychon/x11rb/issues/231
#[test]
fn multithread_test() {
let conn = fake_stream::connect().unwrap();
let conn = Arc::new(conn);
// Auxiliary thread: send requests and wait for replies
let conn1 = conn.clone();
let join = std::thread::spawn(move || {
// Bug #231 sometimes caused `reply` to hang forever.
// Send a huge amount of requests and wait for the reply
// to check if it hangs at some point.
for i in 1..=1_000_000 {
let cookie = conn1.get_input_focus().unwrap();
cookie.reply().unwrap();
if (i % 50_000) == 0 {
eprintln!("{i}");
}
}
eprintln!("all replies received successfully");
// Just anything, we don't care
let event = ClientMessageEvent::new(32, 0, 1u32, [0, 0, 0, 0, 0]);
conn1
.send_event(false, 0u32, EventMask::NO_EVENT, event)
.unwrap();
conn1.flush().unwrap();
});
// Main thread: wait for events until finished
loop {
let event = conn.wait_for_raw_event().unwrap();
if event[0] == CLIENT_MESSAGE_EVENT {
break;
}
}
join.join().unwrap();
}
/// Implementations of `Read` and `Write` that do enough for the test to work.
mod fake_stream {
use std::io::{Error, ErrorKind};
use std::sync::mpsc::{channel, Receiver, Sender};
use std::sync::{Condvar, Mutex};
use x11rb::errors::ConnectError;
use x11rb::protocol::xproto::{
ImageOrder, Setup, CLIENT_MESSAGE_EVENT, GET_INPUT_FOCUS_REQUEST, SEND_EVENT_REQUEST,
};
use x11rb::rust_connection::{PollMode, RustConnection, Stream};
use x11rb::utils::RawFdContainer;
use x11rb_protocol::SequenceNumber;
/// Create a new `RustConnection` connected to a fake stream
pub(crate) fn connect() -> Result<RustConnection<FakeStream>, ConnectError> {
let setup = Setup {
status: 0,
protocol_major_version: 0,
protocol_minor_version: 0,
length: 0,
release_number: 0,
resource_id_base: 0,
resource_id_mask: 0xff,
motion_buffer_size: 0,
maximum_request_length: 0,
image_byte_order: ImageOrder::LSB_FIRST,
bitmap_format_bit_order: ImageOrder::LSB_FIRST,
bitmap_format_scanline_unit: 0,
bitmap_format_scanline_pad: 0,
min_keycode: 0,
max_keycode: 0,
vendor: Vec::new(),
pixmap_formats: Vec::new(),
roots: Vec::new(),
};
let stream = fake_stream();
RustConnection::for_connected_stream(stream, setup)
}
/// Get a pair of fake streams that are connected to each other
fn fake_stream() -> FakeStream {
let (send, recv) = channel();
let pending = Vec::new();
FakeStream {
inner: Mutex::new(FakeStreamInner {
read: FakeStreamRead { recv, pending },
write: FakeStreamWrite {
send,
seqno: 0,
skip: 0,
},
}),
condvar: Condvar::new(),
}
}
/// A packet that still needs to be read from FakeStreamRead
#[derive(Debug)]
enum Packet {
GetInputFocusReply(SequenceNumber),
Event,
}
impl Packet {
fn to_raw(&self) -> Vec<u8> {
match self {
Packet::GetInputFocusReply(seqno) => {
let seqno = (*seqno as u16).to_ne_bytes();
let mut reply = vec![0; 32];
reply[0] = 1; // This is a reply
reply[2..4].copy_from_slice(&seqno);
reply
}
Packet::Event => {
let mut reply = vec![0; 32];
reply[0] = CLIENT_MESSAGE_EVENT;
reply
}
}
}
}
#[derive(Debug)]
pub(crate) struct FakeStream {
inner: Mutex<FakeStreamInner>,
condvar: Condvar,
}
#[derive(Debug)]
struct FakeStreamInner {
read: FakeStreamRead,
write: FakeStreamWrite,
}
#[derive(Debug)]
struct FakeStreamRead {
recv: Receiver<Packet>,
pending: Vec<u8>,
}
#[derive(Debug)]
pub(crate) struct FakeStreamWrite {
send: Sender<Packet>,
seqno: SequenceNumber,
skip: usize,
}
impl Stream for FakeStream {
fn poll(&self, mode: PollMode) -> std::io::Result<()> {
if mode.writable() {
Ok(())
} else {
let mut inner = self.inner.lock().unwrap();
loop {
if inner.read.pending.is_empty() {
let recv_result = inner.read.recv.try_recv();
match recv_result {
Ok(packet) => {
inner.read.pending.extend(packet.to_raw());
return Ok(());
}
Err(std::sync::mpsc::TryRecvError::Empty) => {
inner = self.condvar.wait(inner).unwrap();
}
Err(std::sync::mpsc::TryRecvError::Disconnected) => unreachable!(),
}
} else {
return Ok(());
}
}
}
}
fn read(
&self,
buf: &mut [u8],
_fd_storage: &mut Vec<RawFdContainer>,
) -> std::io::Result<usize> {
let mut inner = self.inner.lock().unwrap();
if inner.read.pending.is_empty() {
let recv_result = inner.read.recv.try_recv();
match recv_result {
Ok(packet) => inner.read.pending.extend(packet.to_raw()),
Err(std::sync::mpsc::TryRecvError::Empty) => {
return Err(Error::new(ErrorKind::WouldBlock, "Would block"));
}
Err(std::sync::mpsc::TryRecvError::Disconnected) => unreachable!(),
}
}
let len = inner.read.pending.len().min(buf.len());
buf[..len].copy_from_slice(&inner.read.pending[..len]);
inner.read.pending.drain(..len);
Ok(len)
}
fn write(&self, buf: &[u8], fds: &mut Vec<RawFdContainer>) -> std::io::Result<usize> {
assert!(fds.is_empty());
let mut inner = self.inner.lock().unwrap();
if inner.write.skip > 0 {
assert_eq!(inner.write.skip, buf.len());
inner.write.skip = 0;
return Ok(buf.len());
}
inner.write.seqno += 1;
match buf[0] {
GET_INPUT_FOCUS_REQUEST => inner
.write
.send
.send(Packet::GetInputFocusReply(inner.write.seqno))
.unwrap(),
SEND_EVENT_REQUEST => inner.write.send.send(Packet::Event).unwrap(),
_ => unimplemented!(),
}
// Compute how much of the package was not yet received
inner.write.skip = usize::from(u16::from_ne_bytes([buf[2], buf[3]])) * 4 - buf.len();
self.condvar.notify_all();
Ok(buf.len())
}
}
}

342
vendor/x11rb/tests/regression_tests.rs vendored Normal file
View File

@@ -0,0 +1,342 @@
use std::cell::RefCell;
use std::io::IoSlice;
use std::ops::Deref;
use x11rb::connection::{
compute_length_field, BufWithFds, ReplyOrError, RequestConnection, RequestKind,
};
use x11rb::cookie::{Cookie, CookieWithFds, VoidCookie};
use x11rb::errors::{ConnectionError, ParseError, ReplyError};
use x11rb::protocol::xproto::{
ClientMessageData, ConnectionExt, KeymapNotifyEvent, Segment, SetupAuthenticate,
};
use x11rb::utils::RawFdContainer;
use x11rb::x11_utils::{ExtensionInformation, Serialize, TryParse, TryParseFd};
use x11rb_protocol::{DiscardMode, SequenceNumber};
#[derive(Debug)]
struct SavedRequest {
has_reply: bool,
data: Vec<u8>,
}
impl SavedRequest {
fn new(has_reply: bool, data: &[IoSlice]) -> SavedRequest {
let data = data
.iter()
.flat_map(|slice| slice.deref())
.copied()
.collect::<Vec<_>>();
SavedRequest { has_reply, data }
}
}
#[derive(Debug, Default)]
struct FakeConnection(RefCell<Vec<SavedRequest>>);
impl FakeConnection {
fn check_requests(&self, expected: &[(bool, Vec<u8>)]) {
let vec = self.0.borrow();
for (expected, actual) in expected.iter().zip(vec.iter()) {
assert_eq!(expected.0, actual.has_reply);
assert_eq!(actual.data, expected.1);
}
assert_eq!(expected.len(), vec.len());
}
fn internal_send_request(
&self,
bufs: &[IoSlice],
fds: Vec<RawFdContainer>,
) -> Result<SequenceNumber, ConnectionError> {
assert_eq!(fds.len(), 0);
let mut storage = Default::default();
let bufs = compute_length_field(self, bufs, &mut storage)?;
self.0.borrow_mut().push(SavedRequest::new(false, bufs));
Ok(0)
}
}
impl RequestConnection for FakeConnection {
type Buf = Vec<u8>;
fn send_request_with_reply<R>(
&self,
bufs: &[IoSlice],
fds: Vec<RawFdContainer>,
) -> Result<Cookie<'_, Self, R>, ConnectionError>
where
R: TryParse,
{
Ok(Cookie::new(self, self.internal_send_request(bufs, fds)?))
}
fn send_request_with_reply_with_fds<R>(
&self,
_bufs: &[IoSlice],
_fds: Vec<RawFdContainer>,
) -> Result<CookieWithFds<'_, Self, R>, ConnectionError>
where
R: TryParseFd,
{
unimplemented!()
}
fn send_request_without_reply(
&self,
bufs: &[IoSlice],
fds: Vec<RawFdContainer>,
) -> Result<VoidCookie<'_, Self>, ConnectionError> {
Ok(VoidCookie::new(
self,
self.internal_send_request(bufs, fds)?,
))
}
fn discard_reply(&self, _sequence: SequenceNumber, _kind: RequestKind, _mode: DiscardMode) {
// Just ignore this
}
fn prefetch_extension_information(
&self,
_extension_name: &'static str,
) -> Result<(), ConnectionError> {
unimplemented!();
}
fn extension_information(
&self,
_extension_name: &'static str,
) -> Result<Option<ExtensionInformation>, ConnectionError> {
unimplemented!()
}
fn wait_for_reply_or_raw_error(
&self,
_sequence: SequenceNumber,
) -> Result<ReplyOrError<Vec<u8>>, ConnectionError> {
unimplemented!()
}
fn wait_for_reply(
&self,
_sequence: SequenceNumber,
) -> Result<Option<Vec<u8>>, ConnectionError> {
unimplemented!()
}
fn wait_for_reply_with_fds_raw(
&self,
_sequence: SequenceNumber,
) -> Result<ReplyOrError<BufWithFds<Vec<u8>>, Vec<u8>>, ConnectionError> {
unimplemented!()
}
fn check_for_raw_error(
&self,
_sequence: SequenceNumber,
) -> Result<Option<Vec<u8>>, ConnectionError> {
unimplemented!()
}
fn maximum_request_bytes(&self) -> usize {
// Must be at least 4 * 2^16 so that we can test BIG-REQUESTS
2usize.pow(19)
}
fn prefetch_maximum_request_bytes(&self) {
unimplemented!()
}
fn parse_error(&self, _error: &[u8]) -> Result<x11rb::x11_utils::X11Error, ParseError> {
unimplemented!()
}
fn parse_event(&self, _event: &[u8]) -> Result<x11rb::protocol::Event, ParseError> {
unimplemented!()
}
}
#[test]
fn test_poly_segment() -> Result<(), ReplyError> {
let conn = FakeConnection::default();
let drawable = 42;
let gc = 0x1337;
let segments = [
Segment {
x1: 1,
y1: 2,
x2: 3,
y2: 4,
},
Segment {
x1: 5,
y1: 6,
x2: 7,
y2: 8,
},
];
let length: u16 = (12 + segments.len() * 8) as u16 / 4;
conn.poly_segment(drawable, gc, &segments)?;
let mut expected = vec![
x11rb::protocol::xproto::POLY_SEGMENT_REQUEST,
0, // padding
];
expected.extend(length.to_ne_bytes()); // length, not in the xml
expected.extend(drawable.to_ne_bytes());
expected.extend(gc.to_ne_bytes());
// Segments
for x in 1u16..9u16 {
expected.extend(x.to_ne_bytes());
}
conn.check_requests(&[(false, expected)]);
Ok(())
}
#[test]
fn test_big_requests() -> Result<(), ConnectionError> {
let conn = FakeConnection::default();
let big_buffer = [0; (1 << 18) + 1];
let drawable: u32 = 42;
let gc: u32 = 0x1337;
let x: i16 = 21;
let y: i16 = 7;
let padding = 3; // big_buffer's size rounded up to a multiple of 4
let big_request_length_field = 4;
let length: u32 = (16 + big_request_length_field + big_buffer.len() as u32 + padding) / 4;
conn.poly_text16(drawable, gc, x, y, &big_buffer)?;
let mut expected = vec![
x11rb::protocol::xproto::POLY_TEXT16_REQUEST,
// padding
0,
// Length of zero: we use big requests
0,
0,
];
// Actual length
expected.extend(length.to_ne_bytes());
expected.extend(drawable.to_ne_bytes());
expected.extend(gc.to_ne_bytes());
expected.extend(x.to_ne_bytes());
expected.extend(y.to_ne_bytes());
expected.extend(big_buffer.iter());
expected.extend((0..padding).map(|_| 0));
conn.check_requests(&[(false, expected)]);
Ok(())
}
#[test]
fn test_too_large_request() {
let conn = FakeConnection::default();
let big_buffer = [0; (1 << 19) + 1];
let drawable: u32 = 42;
let gc: u32 = 0x1337;
let x: i16 = 21;
let y: i16 = 7;
let res = conn.poly_text16(drawable, gc, x, y, &big_buffer);
match res.unwrap_err() {
ConnectionError::MaximumRequestLengthExceeded => {}
err => panic!("Wrong error: {err:?}"),
};
}
#[test]
fn test_send_event() -> Result<(), ConnectionError> {
// Prepare the event
let buffer: [u8; 32] = [
11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30,
];
let event = KeymapNotifyEvent::try_parse(&buffer[..])?.0;
// "Send" it
let conn = FakeConnection::default();
let propagate = true;
let destination: u32 = 0x1337;
let event_mask = x11rb_protocol::protocol::xproto::EventMask::BUTTON3_MOTION;
conn.send_event(propagate, destination, event_mask, event)?;
let mut expected = vec![x11rb::protocol::xproto::SEND_EVENT_REQUEST, propagate as _];
expected.extend(((12u16 + 32u16) / 4).to_ne_bytes());
expected.extend(destination.to_ne_bytes());
expected.extend(u32::from(event_mask).to_ne_bytes());
expected.extend(buffer.iter());
conn.check_requests(&[(false, expected)]);
Ok(())
}
#[test]
fn test_get_keyboard_mapping() -> Result<(), ConnectionError> {
let conn = FakeConnection::default();
let cookie = conn.get_keyboard_mapping(1, 2)?;
// Prevent call to discard_reply(), we only check request sending
std::mem::forget(cookie);
let mut expected = Vec::new();
let length: u16 = 2;
expected.push(101); // request major code
expected.push(0); // padding
expected.extend(length.to_ne_bytes()); // length, not in the xml
expected.push(1); // first keycode
expected.push(2); // length
expected.extend([0, 0]); // padding
conn.check_requests(&[(false, expected)]);
Ok(())
}
#[test]
fn test_client_message_data_parse() {
let short_array = [0, 0, 0];
let err = ClientMessageData::try_parse(&short_array);
assert!(err.is_err());
assert_eq!(err.unwrap_err(), ParseError::InsufficientData);
}
#[test]
fn test_set_modifier_mapping() -> Result<(), ConnectionError> {
let conn = FakeConnection::default();
let cookie = conn.set_modifier_mapping(&(1..17).collect::<Vec<_>>())?;
// Prevent call to discard_reply(), we only check request sending
std::mem::forget(cookie);
let mut expected = Vec::new();
let length: u16 = 5;
expected.push(118); // request major code
expected.push(2); // keycodes per modifier
expected.extend(length.to_ne_bytes()); // length, not in the xml
expected.extend(1u8..17u8);
conn.check_requests(&[(false, expected)]);
Ok(())
}
#[test]
fn test_serialize_setup_authenticate() {
let setup = SetupAuthenticate {
status: 2,
reason: b"12345678".to_vec(),
};
// At the time of writing, the code generator does not produce the correct code...
let length = 2u16.to_ne_bytes();
let setup_bytes = [
2, 0, 0, 0, 0, 0, length[0], length[1], b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8',
];
assert_eq!(&setup_bytes[..], &setup.serialize()[..]);
}
#[cfg(feature = "xinput")]
#[allow(dead_code)]
fn compile_test(conn: &impl RequestConnection) {
use x11rb::protocol::xinput::{xi_query_device, Device};
let _ = xi_query_device(conn, Device::ALL);
}

276
vendor/x11rb/tests/resource_manager.rs vendored Normal file
View File

@@ -0,0 +1,276 @@
#[cfg(feature = "resource_manager")]
mod test {
use std::fs;
use std::io::IoSlice;
use std::path::{Path, PathBuf};
use x11rb::connection::{
BufWithFds, Connection, DiscardMode, RawEventAndSeqNumber, ReplyOrError, RequestConnection,
RequestKind,
};
use x11rb::cookie::{Cookie, CookieWithFds, VoidCookie};
use x11rb::errors::{ConnectionError, ParseError, ReplyOrIdError};
use x11rb::protocol::xproto::{Screen, Setup};
use x11rb::protocol::Event;
use x11rb::resource_manager::{new_from_default, Database};
use x11rb::utils::RawFdContainer;
use x11rb::x11_utils::{ExtensionInformation, Serialize, TryParse, TryParseFd, X11Error};
use x11rb_protocol::SequenceNumber;
// Most tests in here are based on [1], which is: Copyright © 2016 Ingo Bürk
// [1]: https://github.com/Airblader/xcb-util-xrm/blob/master/tests/tests_database.c
/// Get the path to the `target` directory for the current build.
///
/// This is inspired by cargo:
/// https://github.com/rust-lang/cargo/blob/7302186d7beb2b11bf7366c0aa66269313ebe18f/crates/cargo-test-support/src/paths.rs#L18-L31
fn get_temporary_dir(unique_name: &str) -> PathBuf {
let mut path = std::env::current_exe().unwrap();
while path.file_name().and_then(|n| n.to_str()) != Some("target") {
path.pop();
}
path.push("test_data");
path.push(unique_name);
fs::create_dir_all(&path).unwrap();
path
}
fn write_file(base: impl AsRef<Path>, path: impl AsRef<Path>, content: &[u8]) -> PathBuf {
let mut file_path = PathBuf::from(base.as_ref());
file_path.push(path.as_ref());
if let Some(parent) = file_path.parent() {
fs::create_dir_all(parent).unwrap();
}
fs::write(&file_path, content).unwrap();
file_path
}
fn database_from_file(file: impl AsRef<Path>) -> Database {
// I decided against adding something like this to the API...
let file = file.as_ref();
let mut include = Vec::new();
include.extend(b"#include \"");
include.extend(file.file_name().unwrap().to_str().unwrap().bytes());
include.extend(b"\"\n");
Database::new_from_data_with_base_directory(&include, file.parent().unwrap())
}
fn check_db(db: &Database, queries: &[(&str, &[u8])]) {
let mut errors = 0;
for (query, expected) in queries {
let result = db.get_bytes(query, "");
if result != Some(expected) {
eprintln!(
"Queried database for \"{query}\" and expected {expected:?}, but got {result:?}"
);
errors += 1;
}
}
assert_eq!(errors, 0, "Had {errors} errors");
}
#[test]
fn relative_include() {
let dir = get_temporary_dir("relative_include");
let file = write_file(
&dir,
"Xresources1",
b"First: 1\n\n#include \"xresources2\"\n",
);
write_file(
&dir,
"xresources2",
b"#include \"sub/xresources3\"\nSecond: 2\n",
);
write_file(&dir, "sub/xresources3", b"Third: 3\n");
let db = database_from_file(file);
check_db(&db, &[("First", b"1"), ("Second", b"2"), ("Third", b"3")]);
}
#[test]
fn include_loop() {
let dir = get_temporary_dir("include_loop");
let file = write_file(
dir,
"loop.xresources",
b"First: 1\n! Provoke an endless chain of self-inclusion\n#include \"loop.xresources\"\nSecond: 2\n",
);
let db = database_from_file(file);
check_db(&db, &[("First", b"1")]);
}
#[test]
fn home_resolution() {
let mut dir = get_temporary_dir("home_resolution");
write_file(&dir, ".Xresources", b"First: 1\n");
write_file(&dir, "xenvironment", b"Second: 2\n");
std::env::set_var("HOME", &dir);
dir.push("xenvironment");
std::env::set_var("XENVIRONMENT", dir);
let conn = mock_connection(None);
let db = new_from_default(&conn).unwrap();
check_db(&db, &[("First", b"1"), ("Second", b"2")]);
}
#[test]
fn from_resource_manager() {
let conn = mock_connection(Some(b"First: 1\n*Second: 2\n"));
let db = new_from_default(&conn).unwrap();
check_db(&db, &[("First", b"1"), ("Second", b"2")]);
}
/// Create a mock connection that produces the given answer for queries of the RESOURCE_MANAGER
/// property.
fn mock_connection(resource_manager: Option<&[u8]>) -> impl Connection {
// Ugly way to get a default screen: Parse enough zero bytes
let screen = Screen::try_parse(&[0; 100]).unwrap().0;
let mut setup = Setup::try_parse(&[0; 100]).unwrap().0;
setup.roots.push(screen);
MockConnection(setup, resource_manager.map(|v| v.to_vec()))
}
struct MockConnection(Setup, Option<Vec<u8>>);
impl RequestConnection for MockConnection {
type Buf = Vec<u8>;
fn send_request_with_reply<R>(
&self,
_: &[IoSlice<'_>],
_: Vec<RawFdContainer>,
) -> Result<Cookie<'_, Self, R>, ConnectionError>
where
R: TryParse,
{
Ok(Cookie::new(self, 42))
}
fn send_request_with_reply_with_fds<R>(
&self,
_: &[IoSlice<'_>],
_: Vec<RawFdContainer>,
) -> Result<CookieWithFds<'_, Self, R>, ConnectionError>
where
R: TryParseFd,
{
unimplemented!()
}
fn send_request_without_reply(
&self,
_: &[IoSlice<'_>],
_: Vec<RawFdContainer>,
) -> Result<VoidCookie<'_, Self>, ConnectionError> {
unimplemented!()
}
fn discard_reply(&self, _: SequenceNumber, _: RequestKind, _: DiscardMode) {
unimplemented!()
}
fn prefetch_extension_information(&self, _: &'static str) -> Result<(), ConnectionError> {
unimplemented!()
}
fn extension_information(
&self,
_: &'static str,
) -> Result<Option<ExtensionInformation>, ConnectionError> {
unimplemented!()
}
fn wait_for_reply_or_raw_error(
&self,
sequence: SequenceNumber,
) -> Result<ReplyOrError<Self::Buf>, ConnectionError> {
let value = self.1.as_ref().map(|v| &v[..]).unwrap_or(&[]);
// response type
let mut reply = vec![1];
// format
if value.is_empty() {
reply.push(0);
} else {
reply.push(8);
}
// sequence
(sequence as u16).serialize_into(&mut reply);
// length
0u32.serialize_into(&mut reply);
// type (STRING)
31u32.serialize_into(&mut reply);
// bytes_after
0u32.serialize_into(&mut reply);
(value.len() as u32).serialize_into(&mut reply);
// padding
reply.extend([0; 12].iter().copied());
reply.extend(value);
Ok(ReplyOrError::Reply(reply))
}
fn wait_for_reply(&self, _: SequenceNumber) -> Result<Option<Self::Buf>, ConnectionError> {
unimplemented!()
}
fn wait_for_reply_with_fds_raw(
&self,
_: SequenceNumber,
) -> Result<ReplyOrError<BufWithFds<Self::Buf>, Self::Buf>, ConnectionError> {
unimplemented!()
}
fn check_for_raw_error(
&self,
_: SequenceNumber,
) -> Result<Option<Self::Buf>, ConnectionError> {
unimplemented!()
}
fn prefetch_maximum_request_bytes(&self) {
unimplemented!()
}
fn maximum_request_bytes(&self) -> usize {
unimplemented!()
}
fn parse_error(&self, _: &[u8]) -> Result<X11Error, ParseError> {
unimplemented!()
}
fn parse_event(&self, _: &[u8]) -> Result<Event, ParseError> {
unimplemented!()
}
}
impl Connection for MockConnection {
fn wait_for_raw_event_with_sequence(
&self,
) -> Result<RawEventAndSeqNumber<Self::Buf>, ConnectionError> {
unimplemented!()
}
fn poll_for_raw_event_with_sequence(
&self,
) -> Result<Option<RawEventAndSeqNumber<Self::Buf>>, ConnectionError> {
unimplemented!()
}
fn flush(&self) -> Result<(), ConnectionError> {
unimplemented!()
}
fn setup(&self) -> &Setup {
&self.0
}
fn generate_id(&self) -> Result<u32, ReplyOrIdError> {
unimplemented!()
}
}
}

221
vendor/x11rb/tests/x11_utils.rs vendored Normal file
View File

@@ -0,0 +1,221 @@
use ::std::{
collections::HashMap, io::IoSlice, option::Option as RealOption, result::Result as RealResult,
vec::Vec as RealVec,
};
use ::x11rb::{
atom_manager,
connection::{
BufWithFds, DiscardMode, ReplyOrError, RequestConnection, RequestKind, SequenceNumber,
},
cookie::{Cookie, CookieWithFds, VoidCookie},
errors::{ConnectionError, ParseError, ReplyError},
protocol::xproto::{InternAtomReply, INTERN_ATOM_REQUEST},
utils::RawFdContainer,
x11_utils::{ExtensionInformation, Serialize, TryParse, TryParseFd},
};
// Just to be annoying, overwrite some standard types.
// We want to make sure atom_manager! does not use these directly.
mod std {}
mod x11rb {}
#[allow(dead_code)]
type Vec = ();
#[allow(dead_code)]
type Result = ();
#[allow(dead_code)]
type PhantomData = ();
#[allow(dead_code)]
type Option = ();
atom_manager! {
Atoms: AtomsCookies {
FIRST,
SECOND,
THIRD: b"3rd",
LAST,
}
}
struct AtomFakeConnection {
// Mapping from byte string to the corresponding atom value and sequence number.
// If no entry is found, sending the InternAtom request fails.
// If the entry does not fit into u16, fetching the reply fails.
atoms_and_cookies: HashMap<RealVec<u8>, u32>,
}
impl RequestConnection for AtomFakeConnection {
type Buf = RealVec<u8>;
fn send_request_with_reply<R>(
&self,
bufs: &[IoSlice],
_fds: RealVec<RawFdContainer>,
) -> RealResult<Cookie<'_, Self, R>, ConnectionError>
where
R: TryParse,
{
let bytes: RealVec<u8> = bufs.iter().flat_map(|buf| buf.iter().copied()).collect();
// request type and only-if-exists flag
assert_eq!(bytes[..2], [INTERN_ATOM_REQUEST, 0]);
// We ignore the length field
let name_len = usize::from(u16::from_ne_bytes([bytes[4], bytes[5]]));
let name = &bytes[8..(8 + name_len)];
match self.atoms_and_cookies.get(name) {
// We recycle the atom as the sequence number
Some(&atom) => Ok(Cookie::new(self, atom.into())),
None => Err(ConnectionError::UnsupportedExtension),
}
}
fn send_request_with_reply_with_fds<R>(
&self,
_bufs: &[IoSlice],
_fds: RealVec<RawFdContainer>,
) -> RealResult<CookieWithFds<'_, Self, R>, ConnectionError>
where
R: TryParseFd,
{
unimplemented!()
}
fn send_request_without_reply(
&self,
_bufs: &[IoSlice],
_fds: RealVec<RawFdContainer>,
) -> RealResult<VoidCookie<'_, Self>, ConnectionError> {
unimplemented!()
}
fn discard_reply(&self, _sequence: SequenceNumber, _kind: RequestKind, _mode: DiscardMode) {
// Just ignore this
}
fn prefetch_extension_information(
&self,
_extension_name: &'static str,
) -> RealResult<(), ConnectionError> {
unimplemented!();
}
fn extension_information(
&self,
_extension_name: &'static str,
) -> RealResult<RealOption<ExtensionInformation>, ConnectionError> {
unimplemented!()
}
fn wait_for_reply_or_raw_error(
&self,
sequence: SequenceNumber,
) -> RealResult<ReplyOrError<RealVec<u8>>, ConnectionError> {
let sequence_u16 = match u16::try_from(sequence) {
Ok(value) => value,
Err(_) => return Err(ConnectionError::UnsupportedExtension),
};
let reply = InternAtomReply {
length: 0,
sequence: sequence_u16,
atom: sequence.try_into().unwrap(),
};
let mut data = reply.serialize().to_vec();
data.extend([0; 32]);
Ok(ReplyOrError::Reply(data))
}
fn wait_for_reply(
&self,
_sequence: SequenceNumber,
) -> RealResult<RealOption<RealVec<u8>>, ConnectionError> {
unimplemented!()
}
fn wait_for_reply_with_fds_raw(
&self,
_sequence: SequenceNumber,
) -> RealResult<ReplyOrError<BufWithFds<RealVec<u8>>, RealVec<u8>>, ConnectionError> {
unimplemented!()
}
fn check_for_raw_error(
&self,
_sequence: SequenceNumber,
) -> RealResult<RealOption<RealVec<u8>>, ConnectionError> {
unimplemented!()
}
fn maximum_request_bytes(&self) -> usize {
2usize.pow(16)
}
fn prefetch_maximum_request_bytes(&self) {
unimplemented!()
}
fn parse_error(&self, _error: &[u8]) -> RealResult<::x11rb::x11_utils::X11Error, ParseError> {
unimplemented!()
}
fn parse_event(&self, _event: &[u8]) -> RealResult<::x11rb::protocol::Event, ParseError> {
unimplemented!()
}
}
#[test]
fn test_atom_manager_success() {
let conn = AtomFakeConnection {
atoms_and_cookies: [
(b"FIRST".to_vec(), 42),
(b"SECOND".to_vec(), 50),
(b"3rd".to_vec(), 100),
(b"LAST".to_vec(), 200),
]
.into(),
};
let atoms = Atoms::new(&conn).unwrap();
let atoms = atoms.reply().unwrap();
assert_eq!(atoms.FIRST, 42);
assert_eq!(atoms.SECOND, 50);
assert_eq!(atoms.THIRD, 100);
assert_eq!(atoms.LAST, 200);
}
#[test]
fn test_atom_manager_sending_fails() {
let conn = AtomFakeConnection {
atoms_and_cookies: [
(b"FIRST".to_vec(), 42),
(b"3rd".to_vec(), 100),
(b"LAST".to_vec(), 200),
]
.into(),
};
match Atoms::new(&conn) {
// This error is produced in send_request_with_reply() above
Err(ConnectionError::UnsupportedExtension) => {}
Err(err) => panic!("Unexpected error: {err:?}"),
Ok(_) => unreachable!(),
};
}
#[test]
fn test_atom_manager_receiving_fails() {
// A value that does not fit into u16 indicates to AtomFakeConnection that receiving fails
let too_large = u32::from(u16::MAX) * 3;
let conn = AtomFakeConnection {
atoms_and_cookies: [
(b"FIRST".to_vec(), 42),
(b"SECOND".to_vec(), too_large),
(b"3rd".to_vec(), 100),
(b"LAST".to_vec(), 200),
]
.into(),
};
let atoms = Atoms::new(&conn).unwrap();
match atoms.reply() {
// This error is produced in wait_for_reply_or_raw_error() above
Err(ReplyError::ConnectionError(ConnectionError::UnsupportedExtension)) => {}
result => panic!("Unexpected result: {result:?}"),
}
}