test: use parametrized cases

Signed-off-by: blob42 <contact@blob42.xyz>
one-off-cmd
blob42 3 months ago
parent 8869a1e7dc
commit b2785a2f96

213
Cargo.lock generated

@ -66,6 +66,12 @@ version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]]
name = "autocfg"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.5.0" version = "2.5.0"
@ -211,6 +217,101 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "futures"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
name = "futures-core"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
[[package]]
name = "futures-executor"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
[[package]]
name = "futures-macro"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "futures-sink"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
[[package]]
name = "futures-task"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
[[package]]
name = "futures-timer"
version = "3.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24"
[[package]]
name = "futures-util"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.15" version = "0.2.15"
@ -222,6 +323,12 @@ dependencies = [
"wasi", "wasi",
] ]
[[package]]
name = "glob"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.14.5" version = "0.14.5"
@ -327,6 +434,27 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
name = "pin-project-lite"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "proc-macro-crate"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284"
dependencies = [
"toml_edit 0.21.1",
]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.85" version = "1.0.85"
@ -350,6 +478,7 @@ dependencies = [
"memchr", "memchr",
"mock_instant", "mock_instant",
"regex", "regex",
"rstest",
"sd-notify", "sd-notify",
"serde", "serde",
"sysinfo", "sysinfo",
@ -426,12 +555,63 @@ version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
[[package]]
name = "relative-path"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2"
[[package]]
name = "rstest"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9afd55a67069d6e434a95161415f5beeada95a01c7b815508a82dcb0e1593682"
dependencies = [
"futures",
"futures-timer",
"rstest_macros",
"rustc_version",
]
[[package]]
name = "rstest_macros"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4165dfae59a39dd41d8dec720d3cbfbc71f69744efb480a3920f5d4e0cc6798d"
dependencies = [
"cfg-if",
"glob",
"proc-macro-crate",
"proc-macro2",
"quote",
"regex",
"relative-path",
"rustc_version",
"syn",
"unicode-ident",
]
[[package]]
name = "rustc_version"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
dependencies = [
"semver",
]
[[package]] [[package]]
name = "sd-notify" name = "sd-notify"
version = "0.4.2" version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4646d6f919800cd25c50edb49438a1381e2cd4833c027e75e8897981c50b8b5e" checksum = "4646d6f919800cd25c50edb49438a1381e2cd4833c027e75e8897981c50b8b5e"
[[package]]
name = "semver"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.203" version = "1.0.203"
@ -461,6 +641,15 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.11.1" version = "0.11.1"
@ -522,7 +711,7 @@ dependencies = [
"serde", "serde",
"serde_spanned", "serde_spanned",
"toml_datetime", "toml_datetime",
"toml_edit", "toml_edit 0.22.14",
] ]
[[package]] [[package]]
@ -534,6 +723,17 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "toml_edit"
version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1"
dependencies = [
"indexmap",
"toml_datetime",
"winnow 0.5.40",
]
[[package]] [[package]]
name = "toml_edit" name = "toml_edit"
version = "0.22.14" version = "0.22.14"
@ -544,7 +744,7 @@ dependencies = [
"serde", "serde",
"serde_spanned", "serde_spanned",
"toml_datetime", "toml_datetime",
"winnow", "winnow 0.6.13",
] ]
[[package]] [[package]]
@ -745,6 +945,15 @@ version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
[[package]]
name = "winnow"
version = "0.5.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "winnow" name = "winnow"
version = "0.6.13" version = "0.6.13"

@ -2,6 +2,7 @@
name = "pswatch" name = "pswatch"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
default-run = "pswatch"
[[bin]] [[bin]]
@ -26,3 +27,6 @@ serde = { version = "1.0.203", features = ["derive"] }
sysinfo = "0.30.12" sysinfo = "0.30.12"
toml = "0.8.14" toml = "0.8.14"
xdg = "2.5.2" xdg = "2.5.2"
[dev-dependencies]
rstest = "0.21.0"

@ -1,6 +1,7 @@
use std::{fs, path::PathBuf}; use std::{fs, path::PathBuf};
use anyhow::Context; use anyhow::Context;
use log::debug;
use serde::Deserialize; use serde::Deserialize;
use crate::sched::Profile; use crate::sched::Profile;
@ -24,6 +25,8 @@ pub fn read_config(p: Option<PathBuf>) -> anyhow::Result<Config> {
.get_config_file("config.toml"), .get_config_file("config.toml"),
); );
debug!("config file: {:?}", cfg_file);
parse_config( parse_config(
&fs::read_to_string(&cfg_file) &fs::read_to_string(&cfg_file)
.with_context(|| format!("config: {}", cfg_file.display()))?, .with_context(|| format!("config: {}", cfg_file.display()))?,

@ -98,11 +98,17 @@ impl Process {
} }
// process found // process found
} else { } else {
if self.prev_state.is_none() { match self.state {
ProcState::NeverSeen => {
self.first_seen = self.last_refresh; self.first_seen = self.last_refresh;
debug!("<{}>: process seen first time", self.pattern); debug!("<{}>: process seen first time", self.pattern);
} else { },
ProcState::NotSeen => {
debug!("<{}>: process reappeared", self.pattern); debug!("<{}>: process reappeared", self.pattern);
},
ProcState::Seen => {
debug!("<{}>: process still running", self.pattern);
}
} }
self.prev_state = Some(self.state.clone()); self.prev_state = Some(self.state.clone());
self.state = ProcState::Seen; self.state = ProcState::Seen;
@ -181,6 +187,7 @@ enum ProcessMatchBy {
#[cfg(test)] #[cfg(test)]
use mock_instant::global::Instant; use mock_instant::global::Instant;
#[allow(unused_imports)]
mod test { mod test {
use mock_instant::global::MockClock; use mock_instant::global::MockClock;
use crate::sched::Scheduler; use crate::sched::Scheduler;

@ -149,6 +149,7 @@ impl Scheduler {
} }
pub fn new(profiles: Vec<Profile>) -> Self { pub fn new(profiles: Vec<Profile>) -> Self {
debug!("Using sampling rate of {:?}.", Self::SAMPLING_RATE);
let jobs: Vec<ProfileJob> = profiles let jobs: Vec<ProfileJob> = profiles
.iter() .iter()

@ -1,24 +1,31 @@
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use pswatch::{process::{self, ProcCondition}, sched::Scheduler}; use pswatch::{process::{self, ProcCondition}, sched::Scheduler};
use rstest::rstest;
use sysinfo::System; use sysinfo::System;
#[rstest]
#[case((200, 400), true)]
#[case((200, 100), false)]
#[test] #[test]
// cond: seen for 200ms // cond: seen for 200ms
// start state: seen // start state: seen
// test state: seen for 400ms // test state: seen for test_span
//FIX: // (cond_span, test_span, should_match)
fn match_cond_seen() { fn match_cond_seen(
let cond_span = Duration::from_millis(200); #[case] spans: (u64, u64),
let test_span = Duration::from_millis(400); #[case] should_match: bool
) {
let cond_span = Duration::from_millis(spans.0);
let test_span = Duration::from_millis(spans.1);
let mut s = System::new(); let mut s = System::new();
let mut target = std::process::Command::new("tests/5382952proc.sh") let mut target = std::process::Command::new("tests/5382952proc.sh")
.stdout(std::process::Stdio::null()) .stdout(std::process::Stdio::null())
.spawn() .spawn()
.unwrap(); .unwrap();
std::thread::sleep(std::time::Duration::from_secs(1)); std::thread::sleep(std::time::Duration::from_millis(500));
s.refresh_specifics(Scheduler::process_refresh_specs()); s.refresh_specifics(Scheduler::process_refresh_specs());
// process exists // process exists
@ -28,7 +35,6 @@ fn match_cond_seen() {
let pat = "538295"; let pat = "538295";
let mut p = process::Process::from_pattern(pat.into()); let mut p = process::Process::from_pattern(pat.into());
p.refresh(&s, Instant::now()); p.refresh(&s, Instant::now());
dbg!(&p);
let cond = ProcCondition::Seen(cond_span); let cond = ProcCondition::Seen(cond_span);
@ -38,23 +44,32 @@ fn match_cond_seen() {
p.refresh(&s, Instant::now()); p.refresh(&s, Instant::now());
// process exceeded cond // process exceeded cond
assert!(p.matches(cond), "process should be seen"); assert_eq!(p.matches(cond), should_match,
"process should be seen");
let _ = target.kill(); let _ = target.kill();
} }
#[test] // cond: not seen
// cond: not seen for 400ms
// start state: never seen // start state: never seen
// test state: never seen for 1s // test state: never seen for `test_span`
fn match_cond_not_seen() { // (cond_span, test_span, should_match)
let cond_span = Duration::from_millis(400); #[rstest]
let test_span = Duration::from_millis(100); #[case((400, 500), true)]
#[case((400, 300), false)]
#[test]
fn match_cond_not_seen(
#[case] spans: (u64, u64),
#[case] should_match: bool
) {
let cond_span = Duration::from_millis(spans.0);
let test_span = Duration::from_millis(spans.1);
let mut s = System::new(); let mut s = System::new();
std::thread::sleep(std::time::Duration::from_millis(500));
s.refresh_specifics(Scheduler::process_refresh_specs()); s.refresh_specifics(Scheduler::process_refresh_specs());
let cond = ProcCondition::NotSeen(cond_span); let cond = ProcCondition::NotSeen(cond_span);
let pat = "4hxHtngjjkXbA9XJtl9nrs/0kxqjvXnFK79Q8iUzWXo="; let pat = "4hxHtngjjkXbA9XJtl9nrs/0kxqjvXnFK79Q8iUzWXo=";
let mut p = process::Process::from_pattern(pat.into()); let mut p = process::Process::from_pattern(pat.into());
s.refresh_specifics(Scheduler::process_refresh_specs()); s.refresh_specifics(Scheduler::process_refresh_specs());
@ -69,25 +84,35 @@ fn match_cond_not_seen() {
// process exceeded cond // process exceeded cond
let d = t1.elapsed().as_millis(); let d = t1.elapsed().as_millis();
assert!(!p.matches(cond), assert_eq!(p.matches(cond), should_match,
"process is not absent long enough. \ncondition: not_seen({}ms) > observation: not_seen: {}ms", "process is not absent long enough. \ncondition: not_seen({}ms) > observation: not_seen: {}ms",
cond_span.as_millis() ,d); cond_span.as_millis() ,d);
} }
#[test]
// cond: not seen for 400ms // cond: not seen for 400ms
// start state: seen // start state: seen
// test state: not seen for 200ms // test state: not seen for `test_span`
fn match_cond_not_seen_2() { // (cond_span, test_span, should_match)
let cond_span = Duration::from_millis(400); #[rstest]
let test_span = Duration::from_millis(200); #[case((400, 200), false)]
#[test]
fn match_cond_not_seen_2(
#[case] spans: (u64, u64),
#[case] should_match: bool
) {
let cond_span = Duration::from_millis(spans.0);
let test_span = Duration::from_millis(spans.1);
let mut s = System::new(); let mut s = System::new();
s.refresh_specifics(Scheduler::process_refresh_specs()); s.refresh_specifics(Scheduler::process_refresh_specs());
let cond = ProcCondition::NotSeen(cond_span); let cond = ProcCondition::NotSeen(cond_span);
let mut target = std::process::Command::new("tests/5382952proc.sh")
.stdout(std::process::Stdio::null())
.spawn()
.unwrap();
let pat = "4hxHtngjjkXbA9XJtl9nrs/0kxqjvXnFK79Q8iUzWXo="; let pat = "538295";
let mut p = process::Process::from_pattern(pat.into()); let mut p = process::Process::from_pattern(pat.into());
s.refresh_specifics(Scheduler::process_refresh_specs()); s.refresh_specifics(Scheduler::process_refresh_specs());
let t1 = Instant::now(); let t1 = Instant::now();
@ -101,9 +126,10 @@ fn match_cond_not_seen_2() {
// process exceeded cond // process exceeded cond
let d = t1.elapsed().as_millis(); let d = t1.elapsed().as_millis();
assert!(!p.matches(cond), assert_eq!(p.matches(cond), should_match,
"process is not absent long enough. \ncondition: not_seen({}ms) > observation: not_seen: {}ms", "process is not absent long enough. \ncondition: not_seen({}ms) > observation: not_seen: {}ms",
cond_span.as_millis() ,d); cond_span.as_millis() ,d);
let _ = target.kill();
} }

@ -1,13 +1,3 @@
# [[watches]]
# pattern = "foo"
# regex = false
#
# [[watches.commands]]
# # lifetime = {not_seen = "3m"}
# condition = {seen = "5s"}
# exec = ["sh", "-c", "notify-end action!"]
##run_once = false # run the command only once
[[profiles]] [[profiles]]
pattern = "bar" pattern = "bar"
regex = false regex = false
@ -21,3 +11,14 @@ exec = ["sh", "-c", "echo not seen !"]
# when exec_end is defined the schedule behaves like a toggle # when exec_end is defined the schedule behaves like a toggle
# exec_end # exec_end
[[profiles]]
pattern = "foo"
regex = false
[[profiles.commands]]
# lifetime = {not_seen = "3m"}
condition = {not_seen = "5s"}
# one off command
exec = ["sh", "-c", "echo not seen !"]

Loading…
Cancel
Save