diff options
| author | Markus Pettersson <markus.pettersson@mullvad.net> | 2025-10-22 22:12:50 +0200 |
|---|---|---|
| committer | Markus Pettersson <markus.pettersson@mullvad.net> | 2025-10-29 10:25:55 +0100 |
| commit | 6b45195a63ddd79b3e694c2766076a597c375e8f (patch) | |
| tree | d35c3afe62c44727d842303850ecb924c2ec83f1 | |
| parent | 53921838460b68083c81ac42a63348a65e7f401d (diff) | |
| download | mullvadvpn-proptest-update-logic.tar.xz mullvadvpn-proptest-update-logic.zip | |
Test all possible version numbers!proptest-update-logic
| -rw-r--r-- | Cargo.lock | 13 | ||||
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | mullvad-version/Cargo.toml | 4 | ||||
| -rw-r--r-- | mullvad-version/src/lib.rs | 41 |
4 files changed, 53 insertions, 6 deletions
diff --git a/Cargo.lock b/Cargo.lock index 24fbf638dd..9148bcd376 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3406,6 +3406,8 @@ dependencies = [ name = "mullvad-version" version = "0.0.0" dependencies = [ + "proptest", + "proptest-derive", "regex-lite", "serde", ] @@ -4414,6 +4416,17 @@ dependencies = [ ] [[package]] +name = "proptest-derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "095a99f75c69734802359b682be8daaf8980296731f6470434ea2c652af1dd30" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] name = "prost" version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/Cargo.toml b/Cargo.toml index 3f2d2db23e..4032591dc3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -149,6 +149,7 @@ itertools = "0.14" # Test dependencies proptest = "1.8" +proptest-derive = "0.6" insta = { version = "1.42", features = ["yaml"] } [profile.release] diff --git a/mullvad-version/Cargo.toml b/mullvad-version/Cargo.toml index e7a75f93bc..cf1237b617 100644 --- a/mullvad-version/Cargo.toml +++ b/mullvad-version/Cargo.toml @@ -19,3 +19,7 @@ workspace = true [dependencies] regex-lite = "0.1" serde = { workspace = true, optional = true } + +[dev-dependencies] +proptest = { workspace = true } +proptest-derive = { workspace = true } diff --git a/mullvad-version/src/lib.rs b/mullvad-version/src/lib.rs index 6efa48d6a9..89cc4f43ff 100644 --- a/mullvad-version/src/lib.rs +++ b/mullvad-version/src/lib.rs @@ -5,24 +5,43 @@ use std::sync::LazyLock; use regex_lite::Regex; +#[cfg(test)] +use proptest::prelude::proptest; +#[cfg(test)] +use proptest_derive::Arbitrary; + /// The Mullvad VPN app product version #[cfg(has_version)] pub const VERSION: &str = include_str!(concat!(env!("OUT_DIR"), "/product-version.txt")); #[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(test, derive(Arbitrary))] pub struct Version { + #[cfg_attr(test, proptest(strategy = "1000u32..=9999"))] pub year: u32, + #[cfg_attr(test, proptest(strategy = "1u32..=99"))] pub incremental: u32, /// A version can have an optional pre-stable type, e.g. alpha or beta. pub pre_stable: Option<PreStableType>, /// All versions may have an optional -dev-[commit hash] suffix. - pub dev: Option<String>, + pub dev: Option<Hash>, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(test, derive(Arbitrary))] +pub struct Hash(#[cfg_attr(test, proptest(regex = "([0-9a-f]+)"))] String); + +impl Display for Hash { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.0.fmt(f) + } } #[derive(Debug, Clone, Eq, PartialEq, Hash)] +#[cfg_attr(test, derive(Arbitrary))] pub enum PreStableType { - Alpha(u32), - Beta(u32), + Alpha(#[cfg_attr(test, proptest(strategy = "1u32..=999"))] u32), + Beta(#[cfg_attr(test, proptest(strategy = "1u32..=999"))] u32), } impl Ord for PreStableType { @@ -190,7 +209,10 @@ impl FromStr for Version { let alpha = captures.name("alpha").map(|m| m.as_str().parse().unwrap()); let beta = captures.name("beta").map(|m| m.as_str().parse().unwrap()); - let dev = captures.name("dev").map(|m| m.as_str().to_owned()); + let dev = captures + .name("dev") + .map(|m| m.as_str().to_owned()) + .map(Hash); let pre_stable = match (alpha, beta) { (None, None) => None, @@ -373,7 +395,7 @@ mod tests { year: 2021, incremental: 34, pre_stable: None, - dev: Some("0b60e4d87".to_string()), + dev: Some(Hash("0b60e4d87".to_string())), } ); } @@ -386,7 +408,7 @@ mod tests { year: 2024, incremental: 8, pre_stable: Some(PreStableType::Beta(1)), - dev: Some("e5483d".to_string()), + dev: Some(Hash("e5483d".to_string())), } ); } @@ -443,4 +465,11 @@ mod tests { let expected = Version::from_str("2025.11").unwrap(); assert_eq!(parsed.bump(Type::Stable).unwrap(), expected) } + + proptest! { + #[test] + fn parse_all_version_numbers(version: Version) { + parse(&version.to_string()); + } + } } |
