use rust_decimal::Decimal;
use rust_decimal_macros::dec;
use super::{
decimal_to_f64_checked, f64_to_decimal_checked, NonFiniteKind, PrecisionBoundaryError,
PRECISION_SCALE,
};
#[test]
fn decimal_to_f64_preserves_typical_z_score() {
let out = decimal_to_f64_checked(dec!(1.5)).expect("finite Decimal must convert");
assert!((out - 1.5).abs() < 1e-10);
}
#[test]
fn decimal_to_f64_preserves_negative() {
let out = decimal_to_f64_checked(dec!(-2.25)).expect("negative must convert");
assert!((out - -2.25).abs() < 1e-10);
}
#[test]
fn decimal_to_f64_zero() {
let out = decimal_to_f64_checked(Decimal::ZERO).expect("zero must convert");
assert_eq!(out, 0.0);
}
#[test]
fn decimal_to_f64_max_decimal_still_finite() {
let out = decimal_to_f64_checked(Decimal::MAX).expect("Decimal::MAX fits in f64");
assert!(out.is_finite(), "Decimal::MAX ({}) maps to finite f64", out);
}
#[test]
fn f64_to_decimal_rejects_nan() {
let err = f64_to_decimal_checked(f64::NAN).expect_err("NaN must be rejected");
assert_eq!(
err,
PrecisionBoundaryError::NonFiniteInput {
kind: NonFiniteKind::Nan
}
);
}
#[test]
fn f64_to_decimal_rejects_positive_infinity() {
let err = f64_to_decimal_checked(f64::INFINITY).expect_err("+Inf must be rejected");
assert_eq!(
err,
PrecisionBoundaryError::NonFiniteInput {
kind: NonFiniteKind::PositiveInfinity
}
);
}
#[test]
fn f64_to_decimal_rejects_negative_infinity() {
let err = f64_to_decimal_checked(f64::NEG_INFINITY).expect_err("-Inf must be rejected");
assert_eq!(
err,
PrecisionBoundaryError::NonFiniteInput {
kind: NonFiniteKind::NegativeInfinity
}
);
}
#[test]
fn f64_to_decimal_rounds_to_canonical_scale() {
let out = f64_to_decimal_checked(1.234567891).expect("finite must convert");
assert_eq!(out, dec!(1.234568));
assert_eq!(out.scale(), PRECISION_SCALE);
}
#[test]
fn f64_to_decimal_preserves_sign() {
let out = f64_to_decimal_checked(-0.123456).expect("negative must convert");
assert_eq!(out, dec!(-0.123456));
}
#[test]
fn f64_to_decimal_zero_is_exact() {
let out = f64_to_decimal_checked(0.0).expect("0.0 must convert");
assert_eq!(out, Decimal::ZERO);
}
#[test]
fn f64_to_decimal_rejects_value_above_decimal_max() {
let err = f64_to_decimal_checked(1e30).expect_err("1e30 must overflow Decimal");
assert_eq!(
err,
PrecisionBoundaryError::OutOfDomain {
reason: "f64 magnitude exceeds Decimal 96-bit mantissa range"
}
);
}
#[test]
fn roundtrip_is_stable_within_scale() {
let original = dec!(0.987654);
let as_f = decimal_to_f64_checked(original).expect("to f64");
let back = f64_to_decimal_checked(as_f).expect("back to Decimal");
assert_eq!(back, original);
}
#[test]
fn non_finite_kind_display_matches_variant() {
assert_eq!(format!("{}", NonFiniteKind::Nan), "NaN");
assert_eq!(format!("{}", NonFiniteKind::PositiveInfinity), "+Inf");
assert_eq!(format!("{}", NonFiniteKind::NegativeInfinity), "-Inf");
}
#[test]
fn error_display_includes_kind() {
let err = PrecisionBoundaryError::NonFiniteInput {
kind: NonFiniteKind::Nan,
};
assert!(
format!("{}", err).contains("NaN"),
"error display must surface the non-finite kind, got: {}",
err
);
}