From 816b55ef3d84c7d9f3446dab12bf4bec587107fc Mon Sep 17 00:00:00 2001 From: tempoloss <304178922+tempoloss@users.noreply.github.com> Date: Wed, 19 Aug 2026 11:33:00 +0500 Subject: [PATCH] test: An 18-digit amount is rounded by f64 ActiveOrHistoricCurrencyAndAmount.value is f64, which holds integers exactly only below 2^53. 123456789012345678 parses as 123456789012345680 and nothing reports it. The pipeline cannot catch this: the round-trip compares parsed values, so a rounded amount matches itself, and the seven camt053 scenarios carry round balances f64 represents exactly. Feeding this amount through a scenario passes all four steps while the published XML reads 123456789012345680. Below 2^53 the text round-trips exactly, so this bites aggregate balances in currencies like VND or IDR rather than an ordinary CBPR+ payment. --- tests/amount_precision.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 tests/amount_precision.rs diff --git a/tests/amount_precision.rs b/tests/amount_precision.rs new file mode 100644 index 0000000..a295748 --- /dev/null +++ b/tests/amount_precision.rs @@ -0,0 +1,14 @@ +//! ISO 20022 allows an amount 18 significant digits. f64 carries 15. + +use mx_message::document::camt_053_001_08::ActiveOrHistoricCurrencyAndAmount; + +#[test] +fn an_eighteen_digit_amount_is_not_rounded() { + let xml = r#"123456789012345678"#; + let amt: ActiveOrHistoricCurrencyAndAmount = + quick_xml::de::from_str(xml).expect("the amount parses"); + + // Nothing here is exotic: 18 digits is what the standard permits, and the + // nearest f64 to this one is 123456789012345680. + assert_eq!(amt.value.to_string(), "123456789012345678"); +}