feat: 实现模块引入功能以及测试
This commit is contained in:
@@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user