Add some integration tests

This commit is contained in:
Skia 2024-11-04 18:03:49 +01:00
parent f7bcdf1296
commit 3f61dbda90
7 changed files with 1167 additions and 3 deletions

View file

@ -1,17 +1,29 @@
image: "rust:latest"
lint:cargo:
lint:
stage: build
script:
- rustc --version && cargo --version
- rustup component add rustfmt
- cargo fmt
build:cargo:
build:
stage: build
script:
- rustc --version && cargo --version
- cargo build --release
artifacts:
paths:
- target/release/swaysome
- target/release/swaysome
test:integration:
stage: test
script:
- apt update && apt install -y --no-install-recommends sway foot
- adduser test
- chown -R test:test .
- su test <<EOSU # sway won't run as root
- set -e
# This is weird syntax to only run integration tests (the only ones swaysome has)
- cargo test --verbose --test '*'
- EOSU

11
Cargo.lock generated
View file

@ -50,6 +50,16 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "assert-json-diff"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47e4f2b81832e72834d7518d8487a0396a28cc408186a2e8854c0f98011faf12"
dependencies = [
"serde",
"serde_json",
]
[[package]]
name = "byteorder"
version = "1.5.0"
@ -179,6 +189,7 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
name = "swaysome"
version = "2.1.2"
dependencies = [
"assert-json-diff",
"byteorder",
"clap",
"serde",

View file

@ -15,3 +15,6 @@ byteorder = "1.5.0"
clap = { version = "4.4.8", features = ["derive"] }
serde = { version = "1.0.192", features = ["derive"] }
serde_json = "1.0.108"
[dev-dependencies]
assert-json-diff = "2.0.2"

14
HACKING.md Normal file
View file

@ -0,0 +1,14 @@
# Hacking on swaysome
## Get the coverage of the test to improve them
You'll need more toolchain components:
```
rustup component add llvm-tools-preview
```
Then run the tests with coverage profiling, and generate the HTML report:
```
CARGO_INCREMENTAL=0 RUSTFLAGS='-Cinstrument-coverage' LLVM_PROFILE_FILE='cargo-test-%p-%m.profraw' cargo test
grcov . --binary-path ./target/debug/deps/ -s . -t html --branch --ignore-not-existing --ignore '../*' --ignore "/*" -o target/coverage
```

988
tests/integration.rs Normal file
View file

@ -0,0 +1,988 @@
// extern crate assert_json_diff;
use assert_json_diff::{assert_json_eq, assert_json_include};
use serde_json::json;
use swaysome::SwaySome;
mod utils;
use utils::*;
#[test]
fn test_init_three_outputs() {
let sway = Sway::start();
let swaysome = SwaySome::new_from_socket(&sway.sock).expect("SwaySome couldn't initialize");
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "1", "num": 1, "focused": true, "nodes": []},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "2", "num": 2, "focused": false, "nodes": []},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "3", "num": 3, "focused": false, "nodes": []},
]},
]}));
eprintln!("Init 1");
swaysome.init_workspaces(1);
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": true, "nodes": []},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []},
]},
]}));
}
#[test]
fn test_three_outputs_moving_around_same_workspace_group() {
let sway = Sway::start();
let swaysome = SwaySome::new_from_socket(&sway.sock).expect("SwaySome couldn't initialize");
swaysome.init_workspaces(1);
sway.spawn_some_apps();
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": false},
{"name": "TERM2", "focused": false},
{"name": "TERM3", "focused": true},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []},
]},
]}));
eprintln!("Move TERM3 to 2");
swaysome.move_container_to_workspace(2);
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": false},
{"name": "TERM2", "focused": true},
]},
{"type": "workspace", "name": "12", "num": 12, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []},
]},
]}));
eprintln!("Focus to 2");
swaysome.focus_to_workspace(2);
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": false},
{"name": "TERM2", "focused": false},
]},
{"type": "workspace", "name": "12", "num": 12, "focused": false, "nodes": [
{"name": "TERM3", "focused": true},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []},
]},
]}));
}
#[test]
fn test_three_outputs_moving_around_across_workspace_groups() {
let sway = Sway::start();
let swaysome = SwaySome::new_from_socket(&sway.sock).expect("SwaySome couldn't initialize");
swaysome.init_workspaces(1);
sway.spawn_some_apps();
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": false},
{"name": "TERM2", "focused": false},
{"name": "TERM3", "focused": true},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []},
]},
]}));
eprintln!("Move TERM3 to group 2");
swaysome.move_container_to_workspace_group(2);
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": false},
{"name": "TERM2", "focused": true},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []},
]},
]}));
eprintln!("Focus to group 2");
swaysome.focus_to_group(2);
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": false},
{"name": "TERM2", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [
{"name": "TERM3", "focused": true},
]},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []},
]},
]}));
// HEADLESS-3 is still empty
assert_json_eq!(
swaysome.get_tree()["nodes"][3]["nodes"][0]["nodes"],
json!([])
);
eprintln!("Focus to group 1");
swaysome.focus_to_group(1);
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": false},
{"name": "TERM2", "focused": true},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []},
]},
]}));
// HEADLESS-3 is still empty
assert_json_eq!(
swaysome.get_tree()["nodes"][3]["nodes"][0]["nodes"],
json!([])
);
eprintln!("Move TERM2 to group 2");
swaysome.move_container_to_workspace_group(3);
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": true},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [
{"name": "TERM2", "focused": false},
]},
]},
]}));
eprintln!("Focus all to 4");
swaysome.focus_all_outputs_to_workspace(4);
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": false},
]},
{"type": "workspace", "name": "14", "num": 14, "focused": true, "nodes": []},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
{"type": "workspace", "name": "24", "num": 24, "focused": false, "nodes": []},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [
{"name": "TERM2", "focused": false},
]},
{"type": "workspace", "name": "34", "num": 34, "focused": false, "nodes": []},
]},
]}));
eprintln!("Focus all back to 1");
swaysome.focus_all_outputs_to_workspace(1);
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": true},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [
{"name": "TERM2", "focused": false},
]},
]},
]}));
// shadow and re-init swaysome to get up-to-date internals (outputs, workspaces)
// XXX this is more of a hack than anything else. Ideally, swaysome would never have out-of-date internals
let swaysome = SwaySome::new_from_socket(&sway.sock).expect("SwaySome couldn't initialize");
eprintln!("Focus to prev group");
swaysome.focus_to_prev_group();
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "1", "num": 1, "focused": true, "nodes": []},
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [
{"name": "TERM2", "focused": false},
]},
]},
]}));
eprintln!("Focus to prev group again");
swaysome.focus_to_prev_group();
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "1", "num": 1, "focused": false, "nodes": []},
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [
{"name": "TERM2", "focused": true},
]},
]},
]}));
eprintln!("Focus to next group");
swaysome.focus_to_next_group();
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "1", "num": 1, "focused": true, "nodes": []},
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [
{"name": "TERM2", "focused": false},
]},
]},
]}));
eprintln!("Focus to next group again");
swaysome.focus_to_next_group();
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": true},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [
{"name": "TERM2", "focused": false},
]},
]},
]}));
}
#[test]
fn test_three_outputs_moving_around_across_outputs() {
let sway = Sway::start();
let swaysome = SwaySome::new_from_socket(&sway.sock).expect("SwaySome couldn't initialize");
swaysome.init_workspaces(1);
sway.spawn_some_apps();
eprintln!("Move TERM3 to group 3");
swaysome.move_container_to_workspace_group(3);
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": false},
{"name": "TERM2", "focused": true},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
]},
]}));
eprintln!("Move TERM2 to next output");
swaysome.move_container_to_next_output();
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [
{"name": "TERM2", "focused": true},
]},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
]},
]}));
eprintln!("Move TERM2 to prev output");
swaysome.move_container_to_prev_output();
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": false},
{"name": "TERM2", "focused": true},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [
]},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
]},
]}));
eprintln!("Move TERM2 to prev output again");
swaysome.move_container_to_prev_output();
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [
]},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
{"name": "TERM2", "focused": true},
]},
]},
]}));
}
#[test]
fn test_three_outputs_moving_around_across_outputs_without_init() {
let sway = Sway::start();
let swaysome = SwaySome::new_from_socket(&sway.sock).expect("SwaySome couldn't initialize");
sway.spawn_some_apps();
eprintln!("Move TERM3 to group 3");
swaysome.move_container_to_workspace_group(3);
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "1", "num": 1, "focused": false, "nodes": [
{"name": "TERM1", "focused": false},
{"name": "TERM2", "focused": true},
]},
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "2", "num": 2, "focused": false, "nodes": []},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "3", "num": 3, "focused": false, "nodes": []},
]},
]}));
}
#[test]
fn test_three_outputs_moving_around_absolute() {
let sway = Sway::start();
let swaysome = SwaySome::new_from_socket(&sway.sock).expect("SwaySome couldn't initialize");
swaysome.init_workspaces(1);
sway.spawn_some_apps();
// shadow and re-init swaysome to get up-to-date internals (outputs, workspaces)
// XXX this is more of a hack than anything else. Ideally, swaysome would never have out-of-date internals
let swaysome = SwaySome::new_from_socket(&sway.sock).expect("SwaySome couldn't initialize");
eprintln!("Moving TERM3 to 12");
swaysome.move_container_to_workspace(12);
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": false},
{"name": "TERM2", "focused": true},
]},
{"type": "workspace", "name": "12", "num": 12, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []},
]},
]}));
eprintln!("Moving TERM2 to 42");
swaysome.move_container_to_workspace(42);
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": true},
]},
{"type": "workspace", "name": "12", "num": 12, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
{"type": "workspace", "name": "42", "num": 42, "focused": false, "nodes": [
{"name": "TERM2", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []},
]},
]}));
// shadow and re-init swaysome to get up-to-date internals (outputs, workspaces)
// XXX this is more of a hack than anything else. Ideally, swaysome would never have out-of-date internals
let swaysome = SwaySome::new_from_socket(&sway.sock).expect("SwaySome couldn't initialize");
eprintln!("Moving TERM1 to 42");
swaysome.move_container_to_workspace(42);
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": true, "nodes": []},
{"type": "workspace", "name": "12", "num": 12, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
{"type": "workspace", "name": "42", "num": 42, "focused": false, "nodes": [
{"name": "TERM2", "focused": false},
{"name": "TERM1", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []},
]},
]}));
eprintln!("Spawn TERM4");
sway.send_command(["exec", "foot -T TERM4"].as_slice());
std::thread::sleep(std::time::Duration::from_millis(200));
eprintln!("Moving TERM4 to 22");
swaysome.move_container_to_workspace(22);
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": true, "nodes": []},
{"type": "workspace", "name": "12", "num": 12, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
{"type": "workspace", "name": "42", "num": 42, "focused": false, "nodes": [
{"name": "TERM2", "focused": false},
{"name": "TERM1", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []},
{"type": "workspace", "name": "22", "num": 22, "focused": false, "nodes": [
{"name": "TERM4", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []},
]},
]}));
eprintln!("Focus on 42");
swaysome.focus_to_workspace(42);
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "12", "num": 12, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
{"type": "workspace", "name": "42", "num": 42, "focused": false, "nodes": [
{"name": "TERM2", "focused": false},
{"name": "TERM1", "focused": true},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []},
{"type": "workspace", "name": "22", "num": 22, "focused": false, "nodes": [
{"name": "TERM4", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []},
]},
]}));
eprintln!("Focus on 41");
swaysome.focus_to_workspace(41);
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "12", "num": 12, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
{"type": "workspace", "name": "41", "num": 41, "focused": true, "nodes": []},
{"type": "workspace", "name": "42", "num": 42, "focused": false, "nodes": [
{"name": "TERM2", "focused": false},
{"name": "TERM1", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []},
{"type": "workspace", "name": "22", "num": 22, "focused": false, "nodes": [
{"name": "TERM4", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []},
]},
]}));
eprintln!("Focus on 51");
swaysome.focus_to_workspace(51);
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "12", "num": 12, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
{"type": "workspace", "name": "42", "num": 42, "focused": false, "nodes": [
{"name": "TERM2", "focused": false},
{"name": "TERM1", "focused": false},
]},
{"type": "workspace", "name": "51", "num": 51, "focused": true, "nodes": []},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []},
{"type": "workspace", "name": "22", "num": 22, "focused": false, "nodes": [
{"name": "TERM4", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": []},
]},
]}));
eprintln!("Focus on 32");
swaysome.focus_to_workspace(32);
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "12", "num": 12, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
{"type": "workspace", "name": "42", "num": 42, "focused": false, "nodes": [
{"name": "TERM2", "focused": false},
{"name": "TERM1", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []},
{"type": "workspace", "name": "22", "num": 22, "focused": false, "nodes": [
{"name": "TERM4", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "32", "num": 32, "focused": true, "nodes": []},
]},
]}));
}
#[test]
fn test_three_outputs_moving_groups_across_outputs() {
let sway = Sway::start();
let swaysome = SwaySome::new_from_socket(&sway.sock).expect("SwaySome couldn't initialize");
swaysome.init_workspaces(1);
sway.spawn_some_apps();
eprintln!("Move TERM3 to group 3");
swaysome.move_container_to_workspace_group(3);
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": false},
{"name": "TERM2", "focused": true},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
]},
]}));
eprintln!("Move group 1 to prev output");
swaysome.move_workspace_group_to_prev_output();
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "1", "num": 1, "focused": false, "nodes": []},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": false},
{"name": "TERM2", "focused": true},
]},
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
]},
]}));
eprintln!("Move group 1 to next output");
swaysome.move_workspace_group_to_next_output();
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": false},
{"name": "TERM2", "focused": true},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
]},
]}));
eprintln!("Move group 1 to next output again");
swaysome.move_workspace_group_to_next_output();
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "1", "num": 1, "focused": false, "nodes": []},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": false},
{"name": "TERM2", "focused": true},
]},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
]},
]}));
}
#[test]
fn test_three_outputs_plugging_unplugging_outputs() {
let sway = Sway::start();
let swaysome = SwaySome::new_from_socket(&sway.sock).expect("SwaySome couldn't initialize");
swaysome.init_workspaces(1);
sway.spawn_some_apps();
eprintln!("Move TERM3 to group 3");
swaysome.move_container_to_workspace_group(3);
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": false},
{"name": "TERM2", "focused": true},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
]},
]}));
eprintln!("Disabling output 3");
sway.send_command(["output HEADLESS-3 disable"].as_slice());
std::thread::sleep(std::time::Duration::from_millis(200));
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": false},
{"name": "TERM2", "focused": true},
]},
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []},
]},
]}));
assert_eq!(swaysome.get_tree()["nodes"].as_array().unwrap().len(), 3);
eprintln!("Enabling output 3");
sway.send_command(["output HEADLESS-3 enable"].as_slice());
std::thread::sleep(std::time::Duration::from_millis(200));
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": false},
{"name": "TERM2", "focused": true},
]},
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []},
]},
]}));
assert_eq!(swaysome.get_tree()["nodes"].as_array().unwrap().len(), 4);
// shadow and re-init swaysome to get up-to-date internals (outputs, workspaces)
// XXX this is more of a hack than anything else. Ideally, swaysome would never have out-of-date internals
let swaysome = SwaySome::new_from_socket(&sway.sock).expect("SwaySome couldn't initialize");
swaysome.rearrange_workspaces();
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": false},
{"name": "TERM2", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": []},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [
{"name": "TERM3", "focused": true},
]},
]},
]}));
swaysome.focus_to_workspace(11);
swaysome.move_container_to_workspace(21);
eprintln!("Disabling output 2");
sway.send_command(["output HEADLESS-2 disable"].as_slice());
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": true},
]},
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [
{"name": "TERM2", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
]},
]}));
eprintln!("Enabling output 2");
sway.send_command(["output HEADLESS-2 enable"].as_slice());
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": true},
]},
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [
{"name": "TERM2", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [
{"name": "TERM3", "focused": false},
]},
]},
]}));
// shadow and re-init swaysome to get up-to-date internals (outputs, workspaces)
// XXX this is more of a hack than anything else. Ideally, swaysome would never have out-of-date internals
let swaysome = SwaySome::new_from_socket(&sway.sock).expect("SwaySome couldn't initialize");
swaysome.rearrange_workspaces();
assert_json_include!(actual: swaysome.get_tree(), expected: json!({
"nodes": [
{},
{"type": "output", "name": "HEADLESS-1", "current_mode": {"height": 270, "width": 480}, "nodes": [
{"type": "workspace", "name": "11", "num": 11, "focused": false, "nodes": [
{"name": "TERM1", "focused": false},
]},
]},
{"type": "output", "name": "HEADLESS-3", "current_mode": {"height": 1440, "width": 2560}, "nodes": [
{"type": "workspace", "name": "31", "num": 31, "focused": false, "nodes": [
{"name": "TERM3", "focused": true},
]},
]},
{"type": "output", "name": "HEADLESS-2", "current_mode": {"height": 1080, "width": 1920}, "nodes": [
{"type": "workspace", "name": "21", "num": 21, "focused": false, "nodes": [
{"name": "TERM2", "focused": false},
]},
]},
]}));
}

11
tests/sway.conf Normal file
View file

@ -0,0 +1,11 @@
output HEADLESS-1 {
resolution 480x270
}
output HEADLESS-2 {
resolution 1920x1080
}
output HEADLESS-3 {
resolution 2560x1440
}

125
tests/utils/mod.rs Normal file
View file

@ -0,0 +1,125 @@
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")
}
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.
// 50ms 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(200));
self.send_command(["exec", "foot -T TERM2"].as_slice());
std::thread::sleep(std::time::Duration::from_millis(200));
self.send_command(["exec", "foot -T TERM3"].as_slice());
std::thread::sleep(std::time::Duration::from_millis(200));
}
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) {
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();
}
}