Files
komp_ac/steel_decimal/tests/parser_tests.rs
2025-07-05 10:00:04 +02:00

159 lines
5.5 KiB
Rust

use rstest::*;
use steel_decimal::ScriptParser;
use std::collections::HashSet;
#[fixture]
fn parser() -> ScriptParser {
ScriptParser::new()
}
#[rstest]
#[case("(+ 1.5 2.3)", "(decimal-add \"1.5\" \"2.3\")")]
#[case("(- 10 5)", "(decimal-sub \"10\" \"5\")")]
#[case("(* 2.5 4)", "(decimal-mul \"2.5\" \"4\")")]
#[case("(/ 15 3)", "(decimal-div \"15\" \"3\")")]
fn test_basic_arithmetic_transformation(parser: ScriptParser, #[case] input: &str, #[case] expected: &str) {
let result = parser.transform(input);
assert_eq!(result, expected);
}
#[rstest]
#[case("(^ 2 3)", "(decimal-pow \"2\" \"3\")")]
#[case("(** 2 3)", "(decimal-pow \"2\" \"3\")")]
#[case("(pow 2 3)", "(decimal-pow \"2\" \"3\")")]
#[case("(sqrt 16)", "(decimal-sqrt \"16\")")]
#[case("(ln 2.718)", "(decimal-ln \"2.718\")")]
#[case("(log 2.718)", "(decimal-ln \"2.718\")")]
#[case("(log10 100)", "(decimal-log10 \"100\")")]
#[case("(exp 1)", "(decimal-exp \"1\")")]
fn test_advanced_math_transformation(parser: ScriptParser, #[case] input: &str, #[case] expected: &str) {
let result = parser.transform(input);
assert_eq!(result, expected);
}
#[rstest]
#[case("(sin 1.57)", "(decimal-sin \"1.57\")")]
#[case("(cos 0)", "(decimal-cos \"0\")")]
#[case("(tan 0.785)", "(decimal-tan \"0.785\")")]
fn test_trigonometric_transformation(parser: ScriptParser, #[case] input: &str, #[case] expected: &str) {
let result = parser.transform(input);
assert_eq!(result, expected);
}
#[rstest]
#[case("(> 5 3)", "(decimal-gt \"5\" \"3\")")]
#[case("(< 3 5)", "(decimal-lt \"3\" \"5\")")]
#[case("(= 5 5)", "(decimal-eq \"5\" \"5\")")]
#[case("(>= 5 3)", "(decimal-gte \"5\" \"3\")")]
#[case("(<= 3 5)", "(decimal-lte \"3\" \"5\")")]
fn test_comparison_transformation(parser: ScriptParser, #[case] input: &str, #[case] expected: &str) {
let result = parser.transform(input);
assert_eq!(result, expected);
}
#[rstest]
#[case("(abs -5)", "(decimal-abs \"-5\")")]
#[case("(min 3 5)", "(decimal-min \"3\" \"5\")")]
#[case("(max 3 5)", "(decimal-max \"3\" \"5\")")]
#[case("(round 3.14159 2)", "(decimal-round \"3.14159\" \"2\")")]
fn test_utility_transformation(parser: ScriptParser, #[case] input: &str, #[case] expected: &str) {
let result = parser.transform(input);
assert_eq!(result, expected);
}
#[rstest]
#[case("$x", "(get-var \"x\")")]
#[case("$price", "(get-var \"price\")")]
#[case("$some_variable", "(get-var \"some_variable\")")]
fn test_variable_transformation(parser: ScriptParser, #[case] input: &str, #[case] expected: &str) {
let result = parser.transform(input);
assert_eq!(result, expected);
}
#[rstest]
#[case("42", "\"42\"")]
#[case("3.14159", "\"3.14159\"")]
#[case("-5.5", "\"-5.5\"")]
#[case("1.5e2", "\"1.5e2\"")]
#[case("2.3E-1", "\"2.3E-1\"")]
fn test_number_literal_transformation(parser: ScriptParser, #[case] input: &str, #[case] expected: &str) {
let result = parser.transform(input);
assert_eq!(result, expected);
}
#[rstest]
#[case(
"(+ (* 2.5 3.0) (/ 15.0 3.0))",
"(decimal-add (decimal-mul \"2.5\" \"3.0\") (decimal-div \"15.0\" \"3.0\"))"
)]
#[case(
"(sqrt (+ (* $x $x) (* $y $y)))",
"(decimal-sqrt (decimal-add (decimal-mul (get-var \"x\") (get-var \"x\")) (decimal-mul (get-var \"y\") (get-var \"y\"))))"
)]
#[case(
"(/ (+ $a $b) (- $c $d))",
"(decimal-div (decimal-add (get-var \"a\") (get-var \"b\")) (decimal-sub (get-var \"c\") (get-var \"d\")))"
)]
fn test_complex_expressions(parser: ScriptParser, #[case] input: &str, #[case] expected: &str) {
let result = parser.transform(input);
assert_eq!(result, expected);
}
#[rstest]
#[case("(+ $x $y)", vec!["x", "y"])]
#[case("(* $price $quantity)", vec!["price", "quantity"])]
#[case("(/ (+ $a $b) $c)", vec!["a", "b", "c"])]
#[case("(sqrt (+ (* $x $x) (* $y $y)))", vec!["x", "y"])]
fn test_dependency_extraction(parser: ScriptParser, #[case] input: &str, #[case] expected_deps: Vec<&str>) {
let deps = parser.extract_dependencies(input);
let expected: HashSet<String> = expected_deps.into_iter().map(|s| s.to_string()).collect();
assert_eq!(deps, expected);
}
#[rstest]
#[case("(+ 1 2)", "Addition")]
#[case("(- 5 3)", "Subtraction")]
#[case("(* 2 4)", "Multiplication")]
#[case("(/ 8 2)", "Division")]
#[case("(sin 0)", "Trigonometry")]
#[case("(sqrt 16)", "Square root")]
#[case("(> 5 3)", "Comparison")]
fn test_parser_handles_various_functions(parser: ScriptParser, #[case] input: &str, #[case] _description: &str) {
let result = parser.transform(input);
// Should not panic and should produce valid output
assert!(!result.is_empty());
assert!(result.starts_with('('));
assert!(result.ends_with(')'));
}
#[rstest]
fn test_parser_preserves_structure(parser: ScriptParser) {
let input = "(+ (- 10 5) (* 2 3))";
let result = parser.transform(input);
// Check that parentheses are balanced
let open_count = result.chars().filter(|c| *c == '(').count();
let close_count = result.chars().filter(|c| *c == ')').count();
assert_eq!(open_count, close_count);
// Check that the structure is preserved
assert!(result.contains("decimal-add"));
assert!(result.contains("decimal-sub"));
assert!(result.contains("decimal-mul"));
}
#[rstest]
fn test_parser_handles_empty_input(parser: ScriptParser) {
let result = parser.transform("");
assert_eq!(result, "");
}
#[rstest]
fn test_parser_handles_whitespace(parser: ScriptParser) {
let input = "( + 1.5 2.3 )";
let result = parser.transform(input);
assert!(result.contains("decimal-add"));
assert!(result.contains("\"1.5\""));
assert!(result.contains("\"2.3\""));
}