Files
OxideJS-New/crates/oxide_dce/tests/runtime_eq.rs
T
pjh123 b7b6ffd7b1 test: 新增运行时等价对比集成测试(D-08 主验证)
- parse→emit→(dce 开/关)→lower→Vm::run 双管线对比
- 覆盖语句丢弃/重复赋值/if(false)/死闭包/try-catch/对象算术/顶层返回值/先调用后丢弃/const 重赋值
2026-08-06 11:43:39 +08:00

67 lines
3.3 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! 运行时等价对比(D-08):DCE 开/关两份字节码 lower + VM 执行结果一致。
//!
//! 同一 JS 源码走两条管线:parse → emit →(dce 开/关)→ lower → `Vm::run`,
//! 对比顶层执行结果。纯表读错 VM handler 也能被此兜底(D-08)。
//! **不经 `Compiler::compile`**(D-10:测试层直调底层函数,不依赖开关)。
use oxide_vm::vm::Vm;
use oxide_vm::JsValue;
/// parse→emit→(可选 DCE)→lower→run 全链路,返回顶层执行结果。
fn run_source(src: &str, dce: bool) -> Result<JsValue, String> {
let allocator = oxide_parser::Allocator::default();
let program = oxide_parser::parse(&allocator, src).expect("parse failed");
let mut ir = oxide_emit::Emitter::new().emit_program(&program).expect("emit failed");
if dce {
oxide_dce::dce(&mut ir);
}
let module = oxide_ir::lower::lower(&ir).expect("lower failed");
let mut vm = Vm::new();
vm.run(&module)
}
/// 结果规约成可断言形态:`(是否 Ok, 字符串化结果或错误消息)`。
/// Err 双方同为 Err 且消息一致视为一致(如 const 重赋值样例两跑均抛 TypeError)。
fn normalize(r: Result<JsValue, String>) -> (bool, String) {
match r {
Ok(v) => (true, v.to_string()),
Err(e) => (false, e),
}
}
/// 死代码样例集(04-RESEARCH.md Pattern 5 清单)。
/// 对每个样例:DCE 开与关分别执行,断言结果一致。
#[test]
fn dead_code_removed_semantics_preserved() {
// 覆盖:表达式语句丢弃结果、重复赋值只读最后值、if(false) 分支、死闭包、
// try/catch 内死代码、对象操作数算术(D-05 coerce 风险兜底)、
// 顶层表达式返回值(HALT reg0 链,Pitfall 2)、先调用后丢弃(CALL 隐式 reg0,Pitfall 1)、
// const 重赋值抛错保留(Pitfall 5)。
let samples = [
"1+2;3+4", // 语句丢弃结果
"'a'+'b';5;", // 语句丢弃结果(字符串)
"var x=1; x=2; x;", // 重复赋值只读最后值
"function a(){return 1;} if(false){a();} 3;", // if(false) 分支
"function f(){}; 1;", // 死闭包
"try{1+2;}catch(e){3;} 4;", // try/catch 内死代码
"({valueOf(){side=1; return 1}})+2;", // 对象操作数算术(coerce 兜底)
"1+2", // 顶层表达式返回值(Pitfall 2)
"function f(){return 1;} f(); 2+3;", // 先调用后丢弃(Pitfall 1)
"const x=1; x=2;", // const 重赋值(Pitfall 5)
];
for src in samples {
let a = normalize(run_source(src, true));
let b = normalize(run_source(src, false));
assert_eq!(a, b, "DCE 前后语义不一致: {src}");
}
}
/// 单个样例 DCE 开/关断言(失败时给出独立测试名,便于定位)。
#[test]
fn single_sample_top_level_return_value() {
let a = normalize(run_source("1+2", true));
let b = normalize(run_source("1+2", false));
assert_eq!(a, b, "顶层返回值在 DCE 后变化");
assert_eq!(a, (true, "3".to_string()), "顶层 1+2 应返回 3");
}