lemma-engine 0.10.1

A pure, declarative language for business rules.
Documentation
use indexmap::IndexMap;
use lemma::{DateTimeValue, Engine, SourceType};

fn run(code: &str, rule: &str) -> String {
    let mut engine = Engine::new();
    engine
        .load([(SourceType::Volatile, code.to_string())])
        .expect("load");
    let now = DateTimeValue::now();
    let resp = engine
        .evaluate(
            None,
            "test",
            Some(&now),
            IndexMap::new(),
            Some(&[rule.to_string()]),
            false,
        )
        .expect("evaluate");
    let rule_result = resp.get(rule).expect("rule result");
    assert!(!rule_result.vetoed, "rule {rule} vetoed");
    rule_result.result().expect("display").to_string()
}

#[test]
fn ceil_of_value_just_above_integer_is_exact() {
    assert_eq!(
        run("spec test\nrule r: ceil(3 + 1 / 10^29) is 4\n", "r"),
        "true"
    );
    assert_eq!(
        run("spec test\nrule r: ceil(3 + 1 / 10^29) is 3\n", "r"),
        "false"
    );
}

#[test]
fn floor_of_value_just_below_integer_is_exact() {
    assert_eq!(
        run("spec test\nrule r: floor(3 - 1 / 10^29) is 2\n", "r"),
        "true"
    );
}

#[test]
fn floor_and_ceil_of_negative_fractions() {
    assert_eq!(run("spec test\nrule r: floor(-5 / 2) is -3\n", "r"), "true");
    assert_eq!(run("spec test\nrule r: ceil(-5 / 2) is -2\n", "r"), "true");
    assert_eq!(run("spec test\nrule r: ceil(5 / 2) is 3\n", "r"), "true");
}

#[test]
fn abs_then_scale_round_trips_exactly() {
    assert_eq!(run("spec test\nrule r: abs(2 / 3) * 3 is 2\n", "r"), "true");
    assert_eq!(
        run("spec test\nrule r: abs(-2 / 3) * 3 is 2\n", "r"),
        "true"
    );
}

#[test]
fn floor_beyond_decimal_range_is_exact() {
    assert_eq!(
        run("spec test\nrule r: floor(2 ^ 100) is 2 ^ 100\n", "r"),
        "true"
    );
}

#[test]
fn round_half_goes_to_even_and_others_to_nearest() {
    assert_eq!(run("spec test\nrule r: round(5 / 2) is 2\n", "r"), "true");
    assert_eq!(run("spec test\nrule r: round(7 / 2) is 4\n", "r"), "true");
    assert_eq!(run("spec test\nrule r: round(-5 / 2) is -2\n", "r"), "true");
    assert_eq!(run("spec test\nrule r: round(13 / 5) is 3\n", "r"), "true");
    assert_eq!(
        run("spec test\nrule r: round(-13 / 5) is -3\n", "r"),
        "true"
    );
    assert_eq!(run("spec test\nrule r: round(12 / 5) is 2\n", "r"), "true");
}