From e86e211bed0ed190c7ce605eac0a20acacb85082 Mon Sep 17 00:00:00 2001 From: Stephen Waits Date: Tue, 7 Feb 2023 21:37:21 -0700 Subject: [PATCH] test: add property tests to HeightVector Which also helped me fix a bug (using is_sign_negative() when we actually are okay with -0.0). Signed-off-by: Stephen Waits --- proptest-regressions/height_vector.txt | 10 ++++ src/height_vector.rs | 65 ++++++++++++++++++++++++-- 2 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 proptest-regressions/height_vector.txt diff --git a/proptest-regressions/height_vector.txt b/proptest-regressions/height_vector.txt new file mode 100644 index 0000000..493a7d2 --- /dev/null +++ b/proptest-regressions/height_vector.txt @@ -0,0 +1,10 @@ +# Seeds for failure cases proptest has generated in the past. It is +# automatically read and these particular cases re-run before any +# novel cases are generated. +# +# It is recommended to check this file in to source control so that +# everyone who runs the test benefits from these saved cases. +cc 4a5cb6ca844d5306203ae00a99375c83a20ddf4ca427f0ae0b541697efa3d9b7 # shrinks to x = 0.0, y = 0.0, h = -4.122071e-39 +cc 38ed1e2c313317809f5469d856d2c1c61e4851c64a156cd1bdd0757fa7c77128 # shrinks to x = 0.0, y = -0.0, h = 0.0, m = -0.0 +cc b7d1b5e9fe3e33066b583c4532865373179972e9b5786ecc62438f23bc939e87 # shrinks to x = -0.0, y = 0.0, h = -3.448118e-33, m = -0.0 +cc 3c4fc4f21c82ffe5bcbc740ca9ab598e0894226acb86a3046a3a24cbbcdbf8e6 # shrinks to x = 0.0, y = 0.0, h = -0.0 diff --git a/src/height_vector.rs b/src/height_vector.rs index 4b95dcb..a3a720e 100644 --- a/src/height_vector.rs +++ b/src/height_vector.rs @@ -118,7 +118,7 @@ impl HeightVector { /// In this case, valid means the height is positive, and none of the components are NaN or /// Inf. pub(crate) fn is_invalid(&self) -> bool { - self.1.is_sign_negative() || self.1.is_nan() || self.1.is_infinite() || self.0.is_invalid() + self.0.is_invalid() || self.1.is_nan() || self.1.is_infinite() || self.1 < 0.0 } } @@ -193,9 +193,68 @@ impl Mul for HeightVector { // #[cfg(test)] mod tests { - use assert_approx_eq::assert_approx_eq; - use super::*; + use assert_approx_eq::assert_approx_eq; + use proptest::prelude::*; + + proptest! { + #[test] + fn proptest_len(x: f32, y: f32, h: f32) { + let len = ((x*x) + (y*y)).sqrt() + h.abs(); + let a = HeightVector::<2>::from(([x,y],h)); + if x.is_nan() || x.is_infinite() || y.is_nan() || y.is_infinite() || h.is_nan() || h.is_infinite() || h < 0.0 { + // we should've gottne a random univ vector here + assert_approx_eq!(a.len(), 1.0); + } else { + // `HeightVector` we created from proptest values should be valid and have a length + assert_eq!(a.len(), len); + } + } + + #[test] + fn proptest_add(x0 in -1_000_000_000..1_000_000_000i32, y0 in -1_000_000_000..1_000_000_000i32, h0 in 0..1_000_000_000i32, x1 in -1_000_000_000..1_000_000_000i32, y1 in -1_000_000_000..1_000_000_000i32, h1 in 0..1_000_000i32) { + // convert our integer range inputs to f32s + let (fx0,fy0,fh0) = (x0 as f32 / 1_000.0, y0 as f32 / 1_000.0, h0 as f32 / 1_000.0); + let (fx1,fy1,fh1) = (x1 as f32 / 1_000.0, y1 as f32 / 1_000.0, h1 as f32 / 1_000.0); + + let a = HeightVector::<2>::from(([fx0 ,fy0 ],fh0 )); + let b = HeightVector::<2>::from(([fx1 ,fy1 ],fh1 )); + let c = a+b; + assert_eq!(c.0[0], fx0 + fx1); + assert_eq!(c.0[1], fy0 + fy1); + assert_eq!(c.1, fh0 + fh1); + } + + #[test] + fn proptest_sub(x0 in -1_000_000_000..1_000_000_000i32, y0 in -1_000_000_000..1_000_000_000i32, h0 in 0..1_000_000_000i32, x1 in -1_000_000_000..1_000_000_000i32, y1 in -1_000_000_000..1_000_000_000i32, h1 in 0..1_000_000i32) { + // convert our integer range inputs to f32s + let (fx0,fy0,fh0) = (x0 as f32 / 1_000.0, y0 as f32 / 1_000.0, h0 as f32 / 1_000.0); + let (fx1,fy1,fh1) = (x1 as f32 / 1_000.0, y1 as f32 / 1_000.0, h1 as f32 / 1_000.0); + + let a = HeightVector::<2>::from(([fx0 ,fy0 ],fh0 )); + let b = HeightVector::<2>::from(([fx1 ,fy1 ],fh1 )); + let c = a-b; + assert_eq!(c.0[0], fx0 - fx1); + assert_eq!(c.0[1], fy0 - fy1); + assert_eq!(c.1, fh0 + fh1); + } + + #[test] + fn proptest_mul(x in -1_000_000_000..1_000_000_000i32, y in -1_000_000_000..1_000_000_000i32, h in 0..1_000_000_000i32, m in -1_000_000_000..1_000_000_000i32) { + // convert our integer range inputs to f32s + let (fx,fy,fh,fm) = (x as f32 / 1_000.0, y as f32 / 1_000.0, h as f32 / 1_000.0, m as f32 / 1_000.0); + + let a = HeightVector::<2>::from(([fx, fy], fh)); + let b = a * fm; + if fm < 0.0 { + assert_approx_eq!(b.len(), 1.0) + } else { + assert_eq!(b.0[0], fx * fm); + assert_eq!(b.0[1], fy * fm); + assert_eq!(b.1, fh * fm); + } + } + } #[test] fn test_len() {