Files
RustAst/tests/error_recovery.rs
T
Brummel 49ad76e7c3 Refactor: Remove integration tests and organize into modules
This commit refactors the test suite by removing the monolithic
`integration_test.rs` file.
The tests have been categorized and moved into dedicated modules within
the `tests/` directory:

- `tests/parser.rs`: Contains tests for parsing various literal values.
- `tests/destructuring.rs`: Houses tests related to destructuring
  syntax.
- `tests/closures.rs`: Includes tests for closure behavior and related
  optimizations.
- `tests/optimizer.rs`: Contains tests specifically targeting optimizer
  logic and regressions.
- `tests/records.rs`: Holds tests for record syntax and associated
  optimizations.
- `tests/rtl.rs`: Contains tests for runtime library operators and
  functions.
- `tests/pipeline.rs`: Tests for pipeline functionality.
- `tests/macros.rs`: Tests for macro expansion and related issues.
- `tests/error_recovery.rs`: Includes tests for compiler error handling
  and recovery mechanisms.
- `tests/examples.rs`: Verifies the execution of example scripts.

This reorganization improves test discoverability and maintainability.
The `lib.rs` file has also been updated to reflect these changes by
removing the reference to the old `integration_test` module.
The `type_checker.rs` file has had some tests removed, as they are now
covered by the more specific tests in `tests/error_recovery.rs`.
2026-03-21 15:56:07 +01:00

163 lines
4.3 KiB
Rust

use myc::ast::compiler::bound_nodes::TypedNode;
use myc::ast::environment::Environment;
use myc::ast::types::StaticType;
// Helper: extracts the return type from a compiled node.
// For a function type, returns the return type; otherwise returns the node type directly.
fn get_ret_type(node: &TypedNode) -> StaticType {
if let StaticType::Function(sig) = &node.ty {
sig.ret.clone()
} else {
node.ty.clone()
}
}
// --- Type checker errors ---
#[test]
fn test_destructuring_scalar_error() {
let env = Environment::new();
let result = env.compile("(def [x] 5)").into_result();
assert!(result.is_err());
assert_eq!(
result.unwrap_err(),
"Statement 'def' cannot be used as an expression.\nCannot destructure type int as a tuple/vector"
);
}
#[test]
fn test_call_argument_mismatch() {
let env = Environment::new();
// fn takes 1 arg, called with 0
let result = env.compile("(do (def f (fn [x] x)) (f))").into_result();
assert!(result.is_err());
assert!(
result
.unwrap_err()
.contains("Invalid arguments for function call")
);
}
#[test]
fn test_destructuring_vector_args() {
let env = Environment::new();
// ((fn [[x y]] (+ x y)) [10 20]) -> 30
let result = env.compile("((fn [[x y]] (+ x y)) [10 20])").into_result();
assert!(result.is_ok());
assert_eq!(get_ret_type(&result.unwrap()), StaticType::Int);
}
// --- Error recovery (multi-pass diagnostics) ---
#[test]
fn test_error_recovery_parser() {
let env = Environment::new();
// Syntax error: mismatched bracket/paren
let source = "(do (def a [1 2 ) )";
let result = env.compile(source);
assert!(result.diagnostics.has_errors(), "Expected parser errors");
let error_msgs: Vec<_> = result
.diagnostics
.items
.iter()
.map(|d| d.message.as_str())
.collect();
assert!(
error_msgs.iter().any(|m| m.contains("RightParen")),
"Expected error about RightParen"
);
assert!(
result.ast.is_some(),
"AST should be partially built despite parser errors"
);
}
#[test]
fn test_error_recovery_binder() {
let env = Environment::new();
// Semantic error: undefined variable
let source = "(do (def a 10) (def b unknown_var) (+ a 5))";
let result = env.compile(source);
assert!(result.diagnostics.has_errors(), "Expected binder errors");
let error_msgs: Vec<_> = result
.diagnostics
.items
.iter()
.map(|d| d.message.as_str())
.collect();
assert!(
error_msgs
.iter()
.any(|m| m.contains("Undefined variable 'unknown_var'")),
"Expected undefined variable error"
);
assert!(result.ast.is_some(), "AST should be built with Error nodes");
}
#[test]
fn test_error_recovery_type_checker() {
let env = Environment::new();
// Semantic error: Type mismatch in function call
let source = "(do (def a 10) (def b (not \"text\")) (- a 2))";
let result = env.compile(source);
assert!(
result.diagnostics.has_errors(),
"Expected type checker errors"
);
let error_msgs: Vec<_> = result
.diagnostics
.items
.iter()
.map(|d| d.message.as_str())
.collect();
assert!(
error_msgs
.iter()
.any(|m| m.contains("Invalid arguments for function call")),
"Expected invalid arguments error"
);
assert!(result.ast.is_some(), "AST should be built with Error nodes");
}
#[test]
fn test_error_recovery_multiple_errors() {
let env = Environment::new();
// A script with multiple errors that should all be collected
let source = r#"
(do
(def a undefined_var)
(def b (not "text"))
)
"#;
let result = env.compile(source);
assert!(result.diagnostics.has_errors());
assert!(
result.diagnostics.items.len() >= 2,
"Expected multiple errors to be collected"
);
let error_msgs: Vec<_> = result
.diagnostics
.items
.iter()
.map(|d| d.message.as_str())
.collect();
assert!(
error_msgs
.iter()
.any(|m| m.contains("Undefined variable 'undefined_var'"))
);
assert!(
error_msgs
.iter()
.any(|m| m.contains("Invalid arguments for function call"))
);
}