lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

decimal.rs (3711B)


      1 mod common;
      2 
      3 use core::str::FromStr;
      4 
      5 use radroots_core::{Decimal, decimal::Error};
      6 
      7 #[test]
      8 fn display_normalizes_trailing_zeros() {
      9     let d = Decimal::from_str("1.2300").unwrap();
     10     assert_eq!(d.to_string(), "1.23");
     11 }
     12 
     13 #[test]
     14 fn scale_reflects_input_precision() {
     15     let d = Decimal::from_str("1.2300").unwrap();
     16     assert_eq!(d.scale(), 4);
     17 }
     18 
     19 #[test]
     20 fn to_u64_exact_requires_whole_number() {
     21     let whole = common::dec("42.0");
     22     let frac = common::dec("42.5");
     23     assert_eq!(whole.to_u64_exact(), Some(42));
     24     assert_eq!(frac.to_u64_exact(), None);
     25 }
     26 
     27 #[test]
     28 fn from_f64_display_roundtrips_reasonably() {
     29     let d = Decimal::from_f64_display(1.25).unwrap();
     30     let v = d.to_f64_lossy().expect("f64 conversion");
     31     assert!((v - 1.25).abs() < 1e-12);
     32 }
     33 
     34 #[test]
     35 fn parsing_normalizes_zero_and_owns_parse_errors() {
     36     let zero = Decimal::from_str("-0.000").unwrap();
     37     assert_eq!(zero, Decimal::ZERO);
     38     assert_eq!(zero.scale(), 0);
     39     assert_eq!(
     40         Decimal::from_str("not-a-decimal"),
     41         Err(Error::InvalidFormat)
     42     );
     43     assert_eq!(
     44         Decimal::from_str_exact("0.00000000000000000000000000001"),
     45         Err(Error::OutOfRange)
     46     );
     47 }
     48 
     49 #[test]
     50 fn checked_arithmetic_reports_overflow_and_zero_division() {
     51     assert_eq!(
     52         Decimal::MAX.checked_add(Decimal::ONE),
     53         Err(Error::ArithmeticOverflow)
     54     );
     55     assert_eq!(
     56         Decimal::MIN.checked_sub(Decimal::ONE),
     57         Err(Error::ArithmeticOverflow)
     58     );
     59     assert_eq!(
     60         Decimal::MAX.checked_mul(Decimal::from(2u32)),
     61         Err(Error::ArithmeticOverflow)
     62     );
     63     assert_eq!(
     64         Decimal::ONE.checked_div(Decimal::ZERO),
     65         Err(Error::DivisionByZero)
     66     );
     67 }
     68 
     69 #[test]
     70 fn exact_rescale_rejects_rounding_and_unrepresentable_scales() {
     71     let mut exact = Decimal::from_str("1.2300").unwrap();
     72     exact.try_rescale_exact(2).unwrap();
     73     assert_eq!(exact.scale(), 2);
     74     assert_eq!(exact, common::dec("1.23"));
     75 
     76     let mut would_round = common::dec("1.25");
     77     assert_eq!(would_round.try_rescale_exact(1), Err(Error::PrecisionLoss));
     78     assert_eq!(would_round, common::dec("1.25"));
     79 
     80     assert_eq!(
     81         would_round.try_rescale_exact(Decimal::MAX_SCALE + 1),
     82         Err(Error::ScaleOutOfRange)
     83     );
     84 }
     85 
     86 #[test]
     87 fn display_parse_roundtrips_normalized_values() {
     88     for input in ["0", "-42.1250", "999999.000001", "0.00000001"] {
     89         let value = Decimal::from_str(input).unwrap();
     90         let reparsed = Decimal::from_str(&value.to_string()).unwrap();
     91         assert_eq!(reparsed, value);
     92     }
     93 }
     94 
     95 #[test]
     96 fn float_conversion_rejects_non_finite_values() {
     97     assert_eq!(
     98         Decimal::from_f64_display(f64::NAN),
     99         Err(Error::InvalidFormat)
    100     );
    101     assert_eq!(
    102         Decimal::from_f64_display(f64::INFINITY),
    103         Err(Error::InvalidFormat)
    104     );
    105 }
    106 
    107 #[test]
    108 fn from_str_exact_and_primitive_conversion_paths_are_exercised() {
    109     let exact = Decimal::from_str_exact("42.000").unwrap();
    110     assert_eq!(exact, common::dec("42"));
    111 
    112     let from_u32 = Decimal::from(7u32);
    113     let from_i32 = Decimal::from(-2i32);
    114     let from_u64 = Decimal::from(11u64);
    115     let from_i64 = Decimal::from(-9i64);
    116     assert_eq!(from_u32, common::dec("7"));
    117     assert_eq!(from_i32, common::dec("-2"));
    118     assert_eq!(from_u64, common::dec("11"));
    119     assert_eq!(from_i64, common::dec("-9"));
    120 }
    121 
    122 #[cfg(feature = "serde")]
    123 #[test]
    124 fn serde_deserialize_error_paths_are_exercised() {
    125     let parse_err = serde_json::from_str::<Decimal>("\"not-a-decimal\"").unwrap_err();
    126     assert!(!parse_err.to_string().is_empty());
    127     let non_string_err = serde_json::from_str::<Decimal>("123").unwrap_err();
    128     assert!(non_string_err.to_string().contains("invalid type"));
    129 }