units: Extend test coverage for NumOpResult
What changed, and why it matters
This commit only adds new unit tests for an existing Rust type called NumOpResult. It does not change any production code, fix bugs, or alter behavior. There is no security issue here.
No action needed. This is a test-only change with no security relevance.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch extends test coverage in units/src/result.rs and units/src/amount/tests.rs. It adds tests for NumOpResult methods such as map, expect, unwrap, unwrap_err, unwrap_or, unwrap_or_else, ok, and and_then, plus extra assertions for is_overflow and is_div_by_zero. No library code is modified.
Changed components
units/src/result.rsunits/src/amount/tests.rsInspect captured patch +147 / −1
diff --git a/units/src/amount/tests.rs b/units/src/amount/tests.rs
index df3672ad..86fdb9bf 100644
--- a/units/src/amount/tests.rs
+++ b/units/src/amount/tests.rs
@@ -1299,7 +1299,9 @@ fn math_op_errors() {
let overflow = Amount::MAX + Amount::from_sat(1).unwrap();
if let NumOpResult::Error(err) = overflow {
assert!(err.operation().is_overflow());
+ assert!(err.is_overflow());
assert!(!err.operation().is_div_by_zero());
+ assert!(!err.is_div_by_zero());
} else {
panic!("Expected an overflow error, but got a valid result");
}
@@ -1307,7 +1309,9 @@ fn math_op_errors() {
let div_by_zero = Amount::from_sat(10).unwrap() / Amount::ZERO;
if let NumOpResult::Error(err) = div_by_zero {
assert!(!err.operation().is_overflow());
+ assert!(!err.is_overflow());
assert!(err.operation().is_div_by_zero());
+ assert!(err.is_div_by_zero());
} else {
panic!("Expected a division by zero error, but got a valid result");
}
diff --git a/units/src/result.rs b/units/src/result.rs
index 2c1881d3..74acbe79 100644
--- a/units/src/result.rs
+++ b/units/src/result.rs
@@ -439,7 +439,8 @@ impl<'a> Arbitrary<'a> for MathOp {
#[cfg(test)]
mod tests {
- use crate::result::MathOp;
+ use super::{MathOp, NumOpError, NumOpResult};
+ use crate::{Amount, FeeRate, Weight};
#[test]
fn mathop_predicates() {
@@ -466,4 +467,145 @@ mod tests {
assert!(MathOp::Neg.is_negation());
assert!(!MathOp::Add.is_negation());
}
+
+ #[test]
+ fn mathop_map() {
+ // op is evaluated for valid results
+ let res = NumOpResult::Valid(Amount::from_sat_u32(100));
+ let new_value = res.map(|val| (val / FeeRate::from_sat_per_kwu(10)).unwrap());
+ assert_eq!(new_value, NumOpResult::Valid(Weight::from_wu(10_000)));
+
+ // op is not evaluated for error results
+ let res = NumOpResult::<Weight>::Error(NumOpError::while_doing(MathOp::Add));
+ let res_err = res.map(|_| {
+ panic!("map should not evaluate for wrapped error values");
+ });
+ assert_eq!(res_err, res);
+ }
+
+ #[test]
+ fn mathop_expect() {
+ let amounts = [
+ Amount::from_sat_u32(0),
+ Amount::from_sat_u32(10_000_000),
+ Amount::from_sat_u32(u32::MAX),
+ ];
+ for amount in amounts {
+ assert_eq!(
+ NumOpResult::Valid(amount).expect("unreachable"),
+ NumOpResult::Valid(amount).unwrap(),
+ );
+ assert_eq!(NumOpResult::Valid(amount).expect("unreachable"), amount);
+ }
+ }
+
+ #[test]
+ #[should_panic(expected = "test error message")]
+ fn mathop_expect_panics_on_error() {
+ NumOpResult::<Amount>::Error(NumOpError::while_doing(MathOp::Add)).expect("test error message");
+ }
+
+ #[test]
+ fn mathop_unwrap() {
+ let amounts = [
+ Amount::from_sat_u32(0),
+ Amount::from_sat_u32(10_000_000),
+ Amount::from_sat_u32(u32::MAX),
+ ];
+ for amount in amounts {
+ assert_eq!(NumOpResult::Valid(amount).unwrap(), amount);
+ }
+ let weights = [
+ Weight::from_wu(0),
+ Weight::from_wu(16_384_000),
+ Weight::from_wu(u64::MAX),
+ ];
+ for weight in weights {
+ assert_eq!(NumOpResult::Valid(weight).unwrap(), weight);
+ }
+ }
+
+ #[test]
+ #[should_panic(expected = "")]
+ fn mathop_unwrap_panics_on_err() {
+ NumOpResult::<Amount>::Error(NumOpError::while_doing(MathOp::Add)).unwrap();
+ }
+
+ #[test]
+ fn mathop_unwrap_err() {
+ let errs = [
+ NumOpError::while_doing(MathOp::Add),
+ NumOpError::while_doing(MathOp::Sub),
+ NumOpError::while_doing(MathOp::Mul),
+ NumOpError::while_doing(MathOp::Div),
+ NumOpError::while_doing(MathOp::Neg),
+ NumOpError::while_doing(MathOp::Rem),
+ ];
+ for err in errs {
+ assert_eq!(NumOpResult::<Amount>::Error(err).unwrap_err(), err);
+ }
+ }
+
+ #[test]
+ #[should_panic(expected = "")]
+ fn mathop_unwrap_err_panics_on_valid() {
+ let value = Amount::from_sat_u32(150);
+ NumOpResult::<Amount>::Valid(value).unwrap_err();
+ }
+
+ #[test]
+ fn mathop_unwrap_or() {
+ let base_amount = Amount::from_sat_u32(100);
+
+ // default is returned for error results
+ let res = NumOpResult::<Amount>::Error(NumOpError::while_doing(MathOp::Add));
+ let res_default = res.unwrap_or(base_amount);
+ assert_eq!(res_default, base_amount);
+
+ // wrapped value is returned for valid results
+ let res = NumOpResult::Valid(base_amount);
+ let new_amount = res.unwrap_or(Amount::from_sat_u32(50));
+ assert_eq!(new_amount, base_amount);
+ }
+
+ #[test]
+ fn mathop_unwrap_or_else() {
+ let base_amount = Amount::from_sat_u32(100);
+
+ // op is evaluated for error results
+ let res = NumOpResult::<Amount>::Error(NumOpError::while_doing(MathOp::Add));
+ let res_default = res.unwrap_or_else(|| base_amount);
+ assert_eq!(res_default, base_amount);
+
+ // op is not evaluated for valid results
+ let res = NumOpResult::<Amount>::Valid(base_amount);
+ let new_amount = res.unwrap_or_else(|| {
+ panic!("unwrap_or_else should not evaluate for wrapped valid values");
+ });
+ assert_eq!(new_amount, base_amount);
+ }
+
+ #[test]
+ fn mathop_ok() {
+ let amt = Amount::from_sat_u32(150);
+ assert_eq!(NumOpResult::Valid(amt).ok(), Some(amt));
+
+ let err = NumOpError::while_doing(MathOp::Add);
+ assert_eq!(NumOpResult::<Amount>::Error(err).ok(), None);
+ }
+
+ #[test]
+ fn mathop_and_then() {
+ // op is evaluated for valid results
+ let res = NumOpResult::Valid(Amount::from_sat_u32(100));
+ let new_value = res.and_then(|val| val + Amount::from_sat_u32(50));
+ assert_eq!(new_value, NumOpResult::Valid(Amount::from_sat_u32(150)));
+
+ // op is not evaluated for error results
+ let res = NumOpResult::<Amount>::Error(NumOpError::while_doing(MathOp::Add));
+ let res_err = res.and_then(|_| {
+ panic!("and_then should not evaluate for wrapped error values");
+ });
+ assert_eq!(res_err, res);
+ }
}
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.