Skip to content

Commit 147d42b

Browse files
authored
Use Xvfb for automated tests (#37)
* test buttonpress * wait for xephyr to start * install xephyr * start events module * try starting x * /usr/bin/X not found * Only console users are allowed to run the X server * need sudo * forgot sudo echo doesn't work * revert sudo stuff, try -ac * use xvfb not xephyr for automated tests * install libxcb * try a different one * print xcb connection error * specify display for xcb too * delete unused benches * use a labeled block to avoid clippy * try_wait after kill to handle clippy * bring back linux cfg for xcon stuff * xquartz might have xvfb * try lowercase xvfb on mac * more debugging on mac * both xvfb and Xvfb are shown in which but PATH isn't updating
1 parent cc32dc8 commit 147d42b

File tree

4 files changed

+129
-3
lines changed

4 files changed

+129
-3
lines changed

.github/workflows/test.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@ jobs:
2424
if: ${{ ! matrix.is_mac }}
2525
run: |
2626
sudo apt-get update
27-
sudo apt-get install libxft-dev libxinerama-dev
27+
sudo apt-get install libxft-dev libxinerama-dev xserver-xephyr libxcb1-dev
2828
- name: Install X libraries (mac)
2929
if: ${{ matrix.is_mac }}
3030
run: |
3131
brew install libxft libxinerama
32+
brew install --cask xquartz
33+
echo "PATH=$PATH:/opt/X11/bin" >> $GITHUB_ENV
3234
- name: Install ${{ matrix.toolchain }}
3335
uses: dtolnay/rust-toolchain@master
3436
with:
@@ -39,5 +41,3 @@ jobs:
3941
# https://twitter.com/jonhoo/status/1571290371124260865
4042
- name: cargo test --locked
4143
run: cargo test --locked --all-features --lib --bins --tests --examples -- --test-threads=1
42-
- name: cargo bench
43-
run: cargo bench

src/events.rs

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
use x11::xlib::{XButtonEvent, XEvent, _XDisplay};
2+
3+
pub enum Event {
4+
Button(XButtonEvent),
5+
}
6+
7+
impl Event {
8+
pub fn button(
9+
window: u64,
10+
button: u32,
11+
x: i32,
12+
display: *mut _XDisplay,
13+
state: u32,
14+
) -> Self {
15+
Self::Button(XButtonEvent {
16+
type_: 0,
17+
serial: 0,
18+
send_event: 0,
19+
display,
20+
window,
21+
root: 0,
22+
subwindow: 0,
23+
time: 0,
24+
x,
25+
y: 0,
26+
x_root: 0,
27+
y_root: 0,
28+
state,
29+
button,
30+
same_screen: 0,
31+
})
32+
}
33+
34+
pub fn into_button(self) -> XEvent {
35+
match self {
36+
Event::Button(button) => XEvent { button },
37+
}
38+
}
39+
}

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::ffi::{c_char, c_int, c_uint};
33
use enums::Clk;
44

55
pub mod enums;
6+
pub mod events;
67

78
pub type Window = u64;
89

src/main.rs

+86
Original file line numberDiff line numberDiff line change
@@ -2907,3 +2907,89 @@ fn main() {
29072907
drop(Box::from_raw(XCON));
29082908
}
29092909
}
2910+
2911+
#[cfg(test)]
2912+
mod tests {
2913+
use rwm::events::Event;
2914+
use xlib::Button1;
2915+
2916+
use super::*;
2917+
2918+
use std::process::Command;
2919+
2920+
#[test]
2921+
fn main() {
2922+
// setup xephyr
2923+
#[cfg(target_os = "linux")]
2924+
let mut cmd = Command::new("Xvfb").arg(":1").spawn().unwrap();
2925+
2926+
#[cfg(not(target_os = "linux"))]
2927+
let mut cmd = Command::new("xvfb").arg(":1").spawn().unwrap();
2928+
2929+
// wait for xephyr to start
2930+
unsafe {
2931+
while DPY.is_null() {
2932+
DPY = xlib::XOpenDisplay(c":1.0".as_ptr());
2933+
}
2934+
}
2935+
2936+
// goto for killing xephyr no matter what
2937+
let ok = 'defer: {
2938+
#[cfg(target_os = "linux")]
2939+
unsafe {
2940+
let xcon = match Connection::connect(Some(":1.0")) {
2941+
Ok((xcon, _)) => xcon,
2942+
Err(e) => {
2943+
eprintln!("rwm: cannot get xcb connection: {e:?}");
2944+
break 'defer false;
2945+
}
2946+
};
2947+
XCON = Box::into_raw(Box::new(xcon));
2948+
}
2949+
checkotherwm();
2950+
setup();
2951+
scan();
2952+
2953+
// instead of calling `run`, manually send some XEvents
2954+
2955+
// test that a mouse click on the initial (tiling) layout icon
2956+
// switches to floating mode
2957+
handlers::buttonpress(
2958+
&mut Event::button(
2959+
(unsafe { *SELMON }).barwin,
2960+
Button1,
2961+
CONFIG
2962+
.tags
2963+
.iter()
2964+
.map(|tag| textw(tag.as_ptr()))
2965+
.sum::<i32>()
2966+
+ 5,
2967+
unsafe { DPY },
2968+
0,
2969+
)
2970+
.into_button(),
2971+
);
2972+
unsafe {
2973+
assert!((*(*SELMON).lt[(*SELMON).sellt as usize])
2974+
.arrange
2975+
.is_none());
2976+
}
2977+
2978+
cleanup();
2979+
unsafe {
2980+
xlib::XCloseDisplay(DPY);
2981+
2982+
#[cfg(target_os = "linux")]
2983+
drop(Box::from_raw(XCON));
2984+
}
2985+
2986+
break 'defer true;
2987+
};
2988+
2989+
// kill xephyr when finished
2990+
cmd.kill().unwrap();
2991+
cmd.try_wait().unwrap();
2992+
2993+
assert!(ok);
2994+
}
2995+
}

0 commit comments

Comments
 (0)