use std::{
env::{consts::EXE_SUFFIX, current_exe, temp_dir},
path::{Path, PathBuf},
process::Command,
thread::sleep,
time::{Duration, Instant},
};
use nix::{
sys::signal::{
Signal::{SIGINT, SIGUSR1},
kill,
},
unistd::Pid,
};
use serde_json::Value;
fn wl_screenrec() -> PathBuf {
let mut cur = current_exe().unwrap();
cur.pop();
cur.pop();
cur.push(format!("wl-screenrec{}", EXE_SUFFIX));
cur
}
#[test]
fn history_clip_length() {
let filename = temp_dir().join("ahcl.mp4");
let mut cmd = Command::new(dbg!(wl_screenrec()))
.arg("--no-damage")
.arg("--capture-backend=wlr-screencopy")
.arg("--audio")
.arg("--gop-size=5")
.arg("--history=2")
.arg("-f")
.arg(&filename)
.spawn()
.unwrap();
sleep(Duration::from_secs(10));
let pid = Pid::from_raw(cmd.id() as i32);
kill(pid, SIGUSR1).unwrap();
sleep(Duration::from_secs(6));
kill(pid, SIGINT).unwrap();
let wait_start = Instant::now();
cmd.wait().unwrap();
assert!(wait_start.elapsed() < Duration::from_secs(1));
let dur = file_duration(&filename);
println!("dur={dur:?}");
assert!(dur > Duration::from_secs(8), "{:?} < 8s", dur);
assert!(dur < Duration::from_secs_f64(8.5), "{:?} > 8.5s", dur);
}
#[test]
fn scale() {
let filename = temp_dir().join("scale.mp4");
let mut cmd = Command::new(dbg!(wl_screenrec()))
.arg("--no-damage")
.arg("--capture-backend=wlr-screencopy")
.arg("--encode-resolution=128x128")
.arg("-g=0,0 256x256")
.arg("-f")
.arg(&filename)
.spawn()
.unwrap();
sleep(Duration::from_secs(5));
let pid = Pid::from_raw(cmd.id() as i32);
kill(pid, SIGINT).unwrap();
let wait_start = Instant::now();
cmd.wait().unwrap();
assert!(wait_start.elapsed() < Duration::from_secs(1));
assert_eq!(file_resolution(&filename), (128, 128));
}
#[test]
fn basic() {
let filename = temp_dir().join("basic.mp4");
let mut cmd = Command::new(dbg!(wl_screenrec()))
.arg("--no-damage")
.arg("--capture-backend=wlr-screencopy")
.arg("-f")
.arg(&filename)
.spawn()
.unwrap();
let pid = Pid::from_raw(cmd.id() as i32);
sleep(Duration::from_secs(3));
kill(pid, SIGINT).unwrap();
let wait_start = Instant::now();
cmd.wait().unwrap();
assert!(wait_start.elapsed() < Duration::from_secs(1));
let dur = file_duration(&filename);
assert!(dur > Duration::from_secs_f64(2.5), "{:?} < 2.5s", dur);
assert!(dur < Duration::from_secs_f64(3.5), "{:?} > 3.5s", dur);
}
#[cfg(feature = "experimental-vulkan")]
#[test]
fn basic_vulkan() {
let filename = temp_dir().join("basic_vulkan.mp4");
let mut cmd = Command::new(dbg!(wl_screenrec()))
.arg("--no-damage")
.arg("--experimental-vulkan")
.arg("--capture-backend=wlr-screencopy")
.arg("-f")
.arg(&filename)
.spawn()
.unwrap();
let pid = Pid::from_raw(cmd.id() as i32);
sleep(Duration::from_secs(3));
kill(pid, SIGINT).unwrap();
let wait_start = Instant::now();
cmd.wait().unwrap();
assert!(wait_start.elapsed() < Duration::from_secs(1));
let dur = file_duration(&filename);
assert!(dur > Duration::from_secs_f64(2.5), "{:?} < 2.5s", dur);
assert!(dur < Duration::from_secs_f64(3.5), "{:?} > 3.5s", dur);
}
fn file_metadata(filename: &Path) -> Value {
serde_json::from_str(
&String::from_utf8(
Command::new("ffprobe")
.arg("-show_format")
.arg("-show_streams")
.arg("-print_format")
.arg("json")
.arg(&filename)
.output()
.unwrap()
.stdout,
)
.unwrap(),
)
.unwrap()
}
fn file_duration(filename: &Path) -> Duration {
let json = file_metadata(filename);
let dur: f64 = json
.pointer("/format/duration")
.unwrap()
.as_str()
.unwrap()
.parse()
.unwrap();
Duration::from_secs_f64(dur)
}
fn file_resolution(filename: &Path) -> (i64, i64) {
let json = file_metadata(filename);
(
json.pointer("/streams/0/width")
.unwrap()
.as_number()
.unwrap()
.as_i64()
.unwrap(),
json.pointer("/streams/0/height")
.unwrap()
.as_number()
.unwrap()
.as_i64()
.unwrap(),
)
}