mirror of
https://gitlab.com/hyask/swaysome.git
synced 2025-12-10 07:44:43 +01:00
132 lines
4.7 KiB
Rust
132 lines
4.7 KiB
Rust
use std::{
|
|
fs::File,
|
|
io::Read,
|
|
path::PathBuf,
|
|
process::{Child, Command, Output},
|
|
};
|
|
|
|
fn signal(pid: u32, sig: &str) {
|
|
Command::new("kill")
|
|
.arg("-s")
|
|
.arg(sig)
|
|
.arg(format!("{}", pid))
|
|
.status()
|
|
.expect("failed to execute 'kill'");
|
|
}
|
|
|
|
pub struct Sway {
|
|
pub sock: PathBuf,
|
|
process: Child,
|
|
}
|
|
|
|
impl Sway {
|
|
pub fn start() -> Sway {
|
|
let tmp = std::env::temp_dir()
|
|
.join("swaysome_tests")
|
|
.join(std::thread::current().name().unwrap());
|
|
std::fs::create_dir_all(&tmp).expect("Unable to create temporary working directory");
|
|
|
|
let pwd = std::env::current_dir().expect("Unable to get current dir");
|
|
let conf_path = pwd.join("tests/sway.conf");
|
|
let swaysock_path = tmp.join("swaysock");
|
|
let sway_log =
|
|
File::create(tmp.join("sway.log")).expect("Unable to create sway's log file");
|
|
|
|
let sway = Command::new("sway")
|
|
.arg("-c")
|
|
.arg(conf_path.clone())
|
|
.env_clear()
|
|
.env("WLR_BACKENDS", "headless")
|
|
.env("WLR_LIBINPUT_NO_DEVICES", "1")
|
|
.env("XDG_RUNTIME_DIR", &tmp)
|
|
.env("SWAYSOCK", &swaysock_path)
|
|
.stderr(sway_log)
|
|
.spawn()
|
|
.expect("failed to execute sway");
|
|
|
|
// check that sway works correctly without using swaysome
|
|
let sway = Sway {
|
|
sock: swaysock_path,
|
|
process: sway,
|
|
};
|
|
match sway.check_connection("loaded_config_file_name") {
|
|
Ok(()) => {
|
|
// Let's do some common initialization of the desktop
|
|
sway.send_command(["create_output"].as_slice());
|
|
sway.send_command(["create_output"].as_slice());
|
|
return sway;
|
|
}
|
|
Err(()) => {
|
|
eprintln!("Failed to start 'sway', aborting the tests");
|
|
eprintln!("---- sway stderr ----");
|
|
let mut buffer = String::new();
|
|
let mut sway_stderr =
|
|
File::open(tmp.join("sway.log")).expect("Unable to open sway's log file");
|
|
sway_stderr.read_to_string(&mut buffer).unwrap();
|
|
eprintln!("{}", buffer);
|
|
eprintln!("---------------------");
|
|
panic!();
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn send_command(&self, commands: &[&str]) -> Output {
|
|
Command::new("swaymsg")
|
|
.args(commands)
|
|
.env_clear()
|
|
.env("SWAYSOCK", self.sock.clone())
|
|
.output()
|
|
.expect("Couldn't run swaymsg")
|
|
}
|
|
|
|
// work around https://github.com/rust-lang/rust/issues/46379
|
|
// TODO: maybe implement that: https://momori.dev/posts/organize-rust-integration-tests-without-dead-code-warning/
|
|
#[allow(dead_code)]
|
|
pub fn spawn_some_apps(&self) {
|
|
self.send_command(["exec", "foot -T TERM1"].as_slice());
|
|
// Make sure the app are created in the right order.
|
|
// 200ms would still sometimes be racy on my Ryzen 5 PRO 4650U, so let's
|
|
// take a safe bet and give plenty of time for shared CI runners.
|
|
std::thread::sleep(std::time::Duration::from_millis(500));
|
|
self.send_command(["exec", "foot -T TERM2"].as_slice());
|
|
std::thread::sleep(std::time::Duration::from_millis(500));
|
|
self.send_command(["exec", "foot -T TERM3"].as_slice());
|
|
std::thread::sleep(std::time::Duration::from_millis(500));
|
|
}
|
|
|
|
fn check_connection(&self, flag: &str) -> Result<(), ()> {
|
|
let mut retries = 100; // wait for max 10s
|
|
while retries > 0 {
|
|
let version = self.send_command(["-t", "get_version"].as_slice());
|
|
if String::from_utf8(version.stdout).unwrap().contains(flag)
|
|
|| String::from_utf8(version.stderr).unwrap().contains(flag)
|
|
{
|
|
return Ok(());
|
|
}
|
|
std::thread::sleep(std::time::Duration::from_millis(100));
|
|
retries -= 1;
|
|
}
|
|
return Err(());
|
|
}
|
|
|
|
fn stop(&mut self) {
|
|
// in case some apps were spawned, kill them, and give them some time to be killed
|
|
self.send_command(["[all] kill"].as_slice());
|
|
std::thread::sleep(std::time::Duration::from_millis(500));
|
|
// now terminate sway
|
|
signal(self.process.id(), "TERM");
|
|
match self.check_connection("Unable to connect to") {
|
|
Ok(()) => eprintln!("Sway terminated correctly on its own"),
|
|
Err(_) => {
|
|
self.process.kill().expect("Failed to kill sway");
|
|
eprintln!("Sway had to be killed");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Drop for Sway {
|
|
fn drop(&mut self) {
|
|
self.stop();
|
|
}
|
|
}
|