diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index 8abb4e1..cf367b5 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -29,3 +29,15 @@ jobs: components: clippy - uses: Swatinem/rust-cache@v2 - run: cargo clippy --locked --all-targets --all-features --workspace -- -D warnings + test: + runs-on: ubuntu-latest + env: + AW_WEBUI_DIST: ./src/bundle + steps: + - uses: actions/checkout@v3 + - run: sudo apt-get install -y libdbus-1-dev + - uses: dtolnay/rust-toolchain@nightly + with: + components: clippy + - uses: Swatinem/rust-cache@v2 + - run: cargo test --all-features --workspace diff --git a/Cargo.lock b/Cargo.lock index 133a76b..62ceed0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1279,6 +1279,7 @@ checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" dependencies = [ "futures-channel", "futures-core", + "futures-executor", "futures-io", "futures-sink", "futures-task", @@ -1301,6 +1302,17 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +[[package]] +name = "futures-executor" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + [[package]] name = "futures-io" version = "0.3.28" @@ -1322,6 +1334,17 @@ dependencies = [ "waker-fn", ] +[[package]] +name = "futures-macro" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +dependencies = [ + "proc-macro2 1.0.54", + "quote 1.0.26", + "syn 2.0.12", +] + [[package]] name = "futures-sink" version = "0.3.28" @@ -1334,6 +1357,12 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +[[package]] +name = "futures-timer" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" + [[package]] name = "futures-util" version = "0.3.28" @@ -1343,6 +1372,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-io", + "futures-macro", "futures-sink", "futures-task", "memchr", @@ -2766,6 +2796,32 @@ dependencies = [ "uncased", ] +[[package]] +name = "rstest" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de1bb486a691878cd320c2f0d319ba91eeaa2e894066d8b5f8f117c000e9d962" +dependencies = [ + "futures", + "futures-timer", + "rstest_macros", + "rustc_version", +] + +[[package]] +name = "rstest_macros" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290ca1a1c8ca7edb7c3283bd44dc35dd54fdec6253a3912e201ba1072018fca8" +dependencies = [ + "cfg-if 1.0.0", + "proc-macro2 1.0.54", + "quote 1.0.26", + "rustc_version", + "syn 1.0.109", + "unicode-ident", +] + [[package]] name = "rusqlite" version = "0.28.0" @@ -2823,6 +2879,15 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "0.37.3" @@ -2939,6 +3004,12 @@ dependencies = [ "libc", ] +[[package]] +name = "semver" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" + [[package]] name = "serde" version = "1.0.160" @@ -3783,6 +3854,7 @@ dependencies = [ "gethostname 0.4.1", "log", "regex", + "rstest", "serde", "serde_default", "serde_json", diff --git a/watchers/Cargo.toml b/watchers/Cargo.toml index 581d812..e85b89c 100644 --- a/watchers/Cargo.toml +++ b/watchers/Cargo.toml @@ -9,6 +9,9 @@ name = "watchers" crate-type = ["lib"] path = "src/lib.rs" +[dev-dependencies] +rstest = "0.17.0" + [dependencies] aw-client-rust = { git = "https://github.com/ActivityWatch/aw-server-rust" } wayland-client = "0.30.1" diff --git a/watchers/src/config/filters.rs b/watchers/src/config/filters.rs index 36b3b6c..aa38e28 100644 --- a/watchers/src/config/filters.rs +++ b/watchers/src/config/filters.rs @@ -31,7 +31,7 @@ where } } -#[derive(Default)] +#[derive(Default, Debug, PartialEq)] pub struct Replacement { pub replace_app_id: Option, pub replace_title: Option, @@ -86,3 +86,84 @@ impl Filter { Some(replacement) } } + +#[cfg(test)] +mod tests { + use super::*; + use rstest::rstest; + + #[rstest] + #[case::no_match( + (Some("firefox"), Some("Title")), + (None, Some("Secret")), + ("org.kde.dolphin", "/home/user"), + None + )] + #[case::app_id_match( + (Some(".*dolphin"), Some("Title")), + (None, Some("Secret")), + ("org.kde.dolphin", "/home/user"), + None + )] + #[case::title_match( + (Some("firefox"), Some("/home/user")), + (None, Some("Secret")), + ("org.kde.dolphin", "/home/user"), + None + )] + #[case::replace_title( + (Some(".*dolphin"), Some("/home/user")), + (None, Some("Secret")), + ("org.kde.dolphin", "/home/user"), + Some((None, Some("Secret"))) + )] + #[case::replace_app_id( + (Some(".*dolphin"), Some("/home/user")), + (Some("FM"), None), + ("org.kde.dolphin", "/home/user"), + Some((Some("FM"), None)) + )] + #[case::replace( + (Some(".*dolphin"), Some("/home/user")), + (Some("FM"), None), + ("org.kde.dolphin", "/home/user"), + Some((Some("FM"), None)) + )] + #[case::replace_with_catch( + (Some("org\\.kde\\.(.*)"), None), + (Some("$1"), None), + ("org.kde.dolphin", "/home/user"), + Some((Some("dolphin"), None)) + )] + #[case::skip_empty_matches( + (None, None), + (None, Some("Secret")), + ("org.kde.dolphin", "/home/user"), + None + )] + fn replacement( + #[case] matches: (Option<&str>, Option<&str>), + #[case] replaces: (Option<&str>, Option<&str>), + #[case] data: (&str, &str), + #[case] expect_replacement: Option<(Option<&str>, Option<&str>)>, + ) { + let (match_app_id, match_title) = matches; + let (replace_app_id, replace_title) = replaces; + let (app_id, title) = data; + + let option_string = |s: &str| s.to_string(); + let filter = Filter { + match_app_id: match_app_id.map(|s| format!("^{s}$").parse().unwrap()), + match_title: match_title.map(|s| format!("^{s}$").parse().unwrap()), + replace_app_id: replace_app_id.map(option_string), + replace_title: replace_title.map(option_string), + }; + + let replacement = filter.replacement(app_id, title); + let expect_replacement = expect_replacement.map(|r| Replacement { + replace_app_id: r.0.map(option_string), + replace_title: r.1.map(option_string), + }); + assert_eq!(expect_replacement, replacement); + } +} diff --git a/watchers/src/lib.rs b/watchers/src/lib.rs index 3ac420e..34a96e4 100644 --- a/watchers/src/lib.rs +++ b/watchers/src/lib.rs @@ -5,8 +5,8 @@ pub mod config; mod report_client; mod watchers; -pub use report_client::ReportClient; -pub use watchers::ConstructorFilter; -pub use watchers::Watcher; -pub use watchers::ACTIVE_WINDOW; -pub use watchers::IDLE; +pub use crate::report_client::ReportClient; +pub use crate::watchers::ConstructorFilter; +pub use crate::watchers::Watcher; +pub use crate::watchers::ACTIVE_WINDOW; +pub use crate::watchers::IDLE;