lib

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

properties.rs (3934B)


      1 mod common;
      2 
      3 use radroots_core::{Currency, Decimal, Money, Quantity, Unit};
      4 
      5 const VALUES: [&str; 8] = ["-100", "-1.25", "-0.01", "0", "0.01", "1.25", "42", "100"];
      6 const NON_NEGATIVE_VALUES: [&str; 6] = ["0", "0.01", "1", "1.25", "42", "100"];
      7 
      8 #[test]
      9 fn checked_decimal_arithmetic_obeys_ring_laws_on_representative_values() {
     10     for left in VALUES.map(common::dec) {
     11         assert_eq!(left.checked_add(Decimal::ZERO).unwrap(), left);
     12         assert_eq!(left.checked_mul(Decimal::ONE).unwrap(), left);
     13         for right in VALUES.map(common::dec) {
     14             assert_eq!(
     15                 left.checked_add(right).unwrap(),
     16                 right.checked_add(left).unwrap()
     17             );
     18             assert_eq!(
     19                 left.checked_mul(right).unwrap(),
     20                 right.checked_mul(left).unwrap()
     21             );
     22             assert_eq!(
     23                 left.checked_add(right).unwrap().checked_sub(right).unwrap(),
     24                 left
     25             );
     26         }
     27     }
     28 }
     29 
     30 #[test]
     31 fn checked_decimal_multiplication_distributes_over_addition() {
     32     for left in VALUES.map(common::dec) {
     33         for middle in VALUES.map(common::dec) {
     34             for right in VALUES.map(common::dec) {
     35                 let combined = left
     36                     .checked_add(middle)
     37                     .unwrap()
     38                     .checked_mul(right)
     39                     .unwrap();
     40                 let distributed = left
     41                     .checked_mul(right)
     42                     .unwrap()
     43                     .checked_add(middle.checked_mul(right).unwrap())
     44                     .unwrap();
     45                 assert_eq!(combined, distributed);
     46             }
     47         }
     48     }
     49 }
     50 
     51 #[test]
     52 fn checked_money_addition_is_commutative_and_associative() {
     53     for first in NON_NEGATIVE_VALUES.map(common::dec) {
     54         for second in NON_NEGATIVE_VALUES.map(common::dec) {
     55             for third in NON_NEGATIVE_VALUES.map(common::dec) {
     56                 let first = Money::try_new(first, Currency::USD).unwrap();
     57                 let second = Money::try_new(second, Currency::USD).unwrap();
     58                 let third = Money::try_new(third, Currency::USD).unwrap();
     59                 assert_eq!(first.checked_add(&second), second.checked_add(&first));
     60                 assert_eq!(
     61                     first.checked_add(&second).unwrap().checked_add(&third),
     62                     first.checked_add(&second.checked_add(&third).unwrap())
     63                 );
     64             }
     65         }
     66     }
     67 }
     68 
     69 #[test]
     70 fn checked_quantity_addition_preserves_unit_and_is_associative() {
     71     for unit in [Unit::Each, Unit::MassG, Unit::VolumeMl] {
     72         for first in NON_NEGATIVE_VALUES.map(common::dec) {
     73             for second in NON_NEGATIVE_VALUES.map(common::dec) {
     74                 let first = Quantity::try_new(first, unit).unwrap();
     75                 let second = Quantity::try_new(second, unit).unwrap();
     76                 let sum = first.try_add(&second).unwrap();
     77                 assert_eq!(sum.unit(), unit);
     78                 assert_eq!(
     79                     sum.amount(),
     80                     first.amount().checked_add(second.amount()).unwrap()
     81                 );
     82                 assert_eq!(first.try_add(&second), second.try_add(&first));
     83             }
     84         }
     85     }
     86 }
     87 
     88 #[test]
     89 fn canonical_unit_conversion_is_idempotent() {
     90     for (unit, canonical) in [
     91         (Unit::Each, Unit::Each),
     92         (Unit::MassKg, Unit::MassG),
     93         (Unit::MassG, Unit::MassG),
     94         (Unit::MassOz, Unit::MassG),
     95         (Unit::MassLb, Unit::MassG),
     96         (Unit::VolumeL, Unit::VolumeMl),
     97         (Unit::VolumeMl, Unit::VolumeMl),
     98     ] {
     99         for amount in NON_NEGATIVE_VALUES.map(common::dec) {
    100             let quantity = Quantity::try_new(amount, unit).unwrap();
    101             let once = quantity.to_canonical().unwrap();
    102             let twice = once.to_canonical().unwrap();
    103             assert_eq!(once, twice);
    104             assert_eq!(once.unit(), canonical);
    105         }
    106     }
    107 }