feat: 实现模块引入功能以及测试

This commit is contained in:
0264408
2026-06-17 15:57:45 +08:00
parent 9428e270af
commit e356c208a6
17 changed files with 349 additions and 49 deletions
+107
View File
@@ -1626,3 +1626,110 @@ fn error_string_unknown_property() {
});
assert!(result.is_err(), "Expected error for unknown string property");
}
// =========================================================================
// Module system (require)
// =========================================================================
#[test]
fn eval_require_math_module() {
let interp = run("let math = require(\"tests/fixtures/math.ast\");");
let math = get_var(&interp, "math");
match math {
Value::Object(obj) => {
let obj = obj.borrow();
assert!(obj.contains_key("add"), "math should contain 'add'");
assert!(obj.contains_key("mul"), "math should contain 'mul'");
assert!(obj.contains_key("version"), "math should contain 'version'");
}
v => panic!("Expected Object, got {:?}", v),
}
}
#[test]
fn eval_require_call_exported_function() {
let interp = run(r#"
let math = require("tests/fixtures/math.ast");
let result = math.add(10, 32);
"#);
assert_num(&get_var(&interp, "result"), 42.0);
}
#[test]
fn eval_require_cache_returns_same_object() {
let interp = run(r#"
let a = require("tests/fixtures/math.ast");
let b = require("tests/fixtures/math.ast");
let same = a == b;
"#);
assert_bool(&get_var(&interp, "same"), true);
}
#[test]
fn eval_require_module_isolation() {
// 模块看不到调用者的变量,但模块内部定义可以正常工作
let interp = run(r#"
let secret = 99;
let g = require("tests/fixtures/greet.ast");
let msg = g.greet("Aster");
"#);
match get_var(&interp, "msg") {
Value::String(s) => assert_eq!(s, "Hello!"),
v => panic!("Expected String, got {:?}", v),
}
}
#[test]
fn eval_require_module_with_builtins() {
// 模块内部可以使用内置函数(因为 builtins_env 是模块 env 的祖先)
let interp = run(r#"
let m = require("tests/fixtures/math.ast");
let r = m.add(5, 7);
"#);
assert_num(&get_var(&interp, "r"), 12.0);
}
#[test]
fn eval_require_error_file_not_found() {
let result = std::panic::catch_unwind(|| {
run("let x = require(\"nonexistent_file_xyz.ast\");");
});
assert!(result.is_err(), "Expected error for missing module file");
}
#[test]
fn eval_require_error_no_args() {
let result = std::panic::catch_unwind(|| {
run("let x = require();");
});
assert!(result.is_err(), "Expected error for require() with no args");
}
#[test]
fn eval_require_error_non_string_arg() {
let result = std::panic::catch_unwind(|| {
run("let x = require(42);");
});
assert!(result.is_err(), "Expected error for require() with non-string arg");
}
#[test]
fn eval_require_error_broken_syntax() {
let result = std::panic::catch_unwind(|| {
run("let x = require(\"tests/fixtures/broken_syntax.ast\");");
});
assert!(result.is_err(), "Expected error for module with syntax error");
}
#[test]
fn eval_require_empty_module() {
// 空模块应该返回空对象
let interp = run("let empty = require(\"tests/fixtures/sub/mod.ast\");");
match get_var(&interp, "empty") {
Value::Object(obj) => {
let obj = obj.borrow();
assert!(obj.contains_key("sub"), "empty module should contain 'sub'");
}
v => panic!("Expected Object, got {:?}", v),
}
}