diff --git a/libs/utils/src/approx_accurate.rs b/libs/utils/src/approx_accurate.rs index 5de3461521..e7af36eec4 100644 --- a/libs/utils/src/approx_accurate.rs +++ b/libs/utils/src/approx_accurate.rs @@ -4,7 +4,7 @@ /// If a single `None` value is merged, it becomes `Approximate` variant. /// /// Remove when `Layer::file_size` is no longer an `Option`. -#[derive(Default, Debug)] +#[derive(Default, Debug, Clone, Copy)] pub enum ApproxAccurate { Approximate(T), Accurate(T), @@ -49,3 +49,52 @@ impl ApproxAccurate { } } } + +#[cfg(test)] +mod tests { + use super::ApproxAccurate; + + #[test] + fn accumulate_only_some() { + let acc = (0..=5) + .into_iter() + .map(Some) + .fold(ApproxAccurate::default(), |acc, next| acc.max(next)); + + assert_eq!(acc.accurate(), Some(5)); + assert!(!acc.is_approximate()); + assert_eq!(acc.unwrap_accurate_or(42), 5); + } + + #[test] + fn accumulate_some_and_none() { + let acc = [Some(0), None, Some(2)] + .into_iter() + .fold(ApproxAccurate::default(), |acc, next| acc.max(next)); + + assert_eq!(acc.accurate(), None); + assert!(acc.is_approximate()); + assert_eq!(acc.unwrap_accurate_or(42), 42); + } + + #[test] + fn accumulate_none_and_some() { + let acc = [None, Some(1), None] + .into_iter() + .fold(ApproxAccurate::default(), |acc, next| acc.max(next)); + + assert_eq!(acc.accurate(), None); + assert!(acc.is_approximate()); + assert_eq!(acc.unwrap_accurate_or(42), 42); + } + + #[test] + fn accumulate_none() { + let acc = ApproxAccurate::::default(); + + // it is accurate empty + assert_eq!(acc.accurate(), Some(0)); + assert!(!acc.is_approximate()); + assert_eq!(acc.unwrap_accurate_or(42), 0); + } +}