test: test262 支持不跳过测试模式

This commit is contained in:
爱特每羊队
2026-06-09 10:25:22 +08:00
parent 77384b20f0
commit f54383ef63
+77 -11
View File
@@ -108,6 +108,48 @@ struct RunStats {
fail_categories: HashMap<String, usize>, fail_categories: HashMap<String, usize>,
} }
#[derive(Debug, Default)]
struct RunConfig {
test262_root: Option<PathBuf>,
filter: Option<String>,
no_skip: bool,
}
impl RunConfig {
fn parse(args: &[String]) -> Result<Self, String> {
let mut config = Self::default();
let mut positional = Vec::new();
for arg in args.iter().skip(1) {
match arg.as_str() {
"--no-skip" => config.no_skip = true,
"--help" | "-h" => return Err(Self::usage()),
_ if arg.starts_with("--") => return Err(format!("unknown option: {arg}\n\n{}", Self::usage())),
_ => positional.push(arg.clone()),
}
}
if let Some(root) = positional.first() {
config.test262_root = Some(PathBuf::from(root));
}
if let Some(filter) = positional.get(1) {
config.filter = Some(filter.clone());
}
if positional.len() > 2 {
return Err(format!("too many positional arguments\n\n{}", Self::usage()));
}
Ok(config)
}
fn usage() -> String {
"usage: test262-runner [--no-skip] [test262-root] [path-filter]\n\
\n\
--no-skip Run capability-excluded tests and count unsupported compile/runtime results as failures."
.into()
}
}
fn is_skipped(meta: &TestMeta) -> Option<String> { fn is_skipped(meta: &TestMeta) -> Option<String> {
for flag in &meta.flags { for flag in &meta.flags {
match flag.as_str() { match flag.as_str() {
@@ -202,11 +244,12 @@ Test262Error.prototype.constructor = Test262Error;
fn run_test( fn run_test(
path: &Path, source: &str, meta: &TestMeta, kernel: &Arc<OxideKernel>, harness_module: &CompiledModule, path: &Path, source: &str, meta: &TestMeta, kernel: &Arc<OxideKernel>, harness_module: &CompiledModule,
no_skip: bool,
) -> TestResult { ) -> TestResult {
let start = std::time::Instant::now(); let start = std::time::Instant::now();
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
run_test_inner(path, source, meta, kernel, harness_module) run_test_inner(path, source, meta, kernel, harness_module, no_skip)
})); }));
match result { match result {
@@ -220,6 +263,7 @@ fn run_test(
fn run_test_inner( fn run_test_inner(
path: &Path, source: &str, meta: &TestMeta, kernel: &Arc<OxideKernel>, harness_module: &CompiledModule, path: &Path, source: &str, meta: &TestMeta, kernel: &Arc<OxideKernel>, harness_module: &CompiledModule,
no_skip: bool,
) -> TestResult { ) -> TestResult {
let start = std::time::Instant::now(); let start = std::time::Instant::now();
@@ -259,6 +303,9 @@ fn run_test_inner(
|| e.contains("before initialization") || e.contains("before initialization")
|| e.contains("parser panicked") || e.contains("parser panicked")
{ {
if no_skip {
return TestResult::fail(path.to_path_buf(), dur, msg);
}
return TestResult::skip(path.to_path_buf(), msg); return TestResult::skip(path.to_path_buf(), msg);
} }
return TestResult::fail(path.to_path_buf(), dur, msg); return TestResult::fail(path.to_path_buf(), dur, msg);
@@ -268,8 +315,12 @@ fn run_test_inner(
let mut vm = Vm::with_kernel(Arc::clone(kernel)); let mut vm = Vm::with_kernel(Arc::clone(kernel));
if let Err(e) = vm.run(harness_module) { if let Err(e) = vm.run(harness_module) {
let _dur = start.elapsed().as_millis() as u64; let dur = start.elapsed().as_millis() as u64;
return TestResult::skip(path.to_path_buf(), format!("harness injection failed: {e}")); let msg = format!("harness injection failed: {e}");
if no_skip {
return TestResult::fail(path.to_path_buf(), dur, msg);
}
return TestResult::skip(path.to_path_buf(), msg);
} }
match vm.run(&module) { match vm.run(&module) {
@@ -309,6 +360,9 @@ fn run_test_inner(
|| e.contains("NEW_EXPRESSION") || e.contains("NEW_EXPRESSION")
|| e.contains("RangeError") || e.contains("RangeError")
{ {
if no_skip {
return TestResult::fail(path.to_path_buf(), dur, format!("vm error: {e}"));
}
TestResult::skip(path.to_path_buf(), format!("vm: {e}")) TestResult::skip(path.to_path_buf(), format!("vm: {e}"))
} else { } else {
TestResult::fail(path.to_path_buf(), dur, format!("vm error: {e}")) TestResult::fail(path.to_path_buf(), dur, format!("vm error: {e}"))
@@ -386,9 +440,16 @@ fn main() {
fn run_tests() -> bool { fn run_tests() -> bool {
let args: Vec<String> = std::env::args().collect(); let args: Vec<String> = std::env::args().collect();
let config = match RunConfig::parse(&args) {
Ok(config) => config,
Err(msg) => {
eprintln!("{msg}");
return false;
}
};
let test262_root = if args.len() > 1 { let test262_root = if let Some(root) = config.test262_root.clone() {
PathBuf::from(&args[1]) root
} else { } else {
let mut p = PathBuf::from(env!("CARGO_MANIFEST_DIR")); let mut p = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
p.pop(); p.pop();
@@ -410,9 +471,12 @@ fn run_tests() -> bool {
std::process::exit(1); std::process::exit(1);
} }
let filter = if args.len() > 2 { Some(args[2].clone()) } else { None }; let filter = config.filter.clone();
eprintln!("discovering tests in: {}", test262_root.display()); eprintln!("discovering tests in: {}", test262_root.display());
if config.no_skip {
eprintln!("no-skip mode: capability filters disabled; unsupported results count as failures");
}
let paths = discover_tests(&test262_root); let paths = discover_tests(&test262_root);
eprintln!("found {} test files", paths.len()); eprintln!("found {} test files", paths.len());
@@ -478,13 +542,15 @@ fn run_tests() -> bool {
continue; continue;
} }
if let Some(reason) = is_skipped(&meta) { if !config.no_skip {
results.push(TestResult::skip(path.clone(), reason)); if let Some(reason) = is_skipped(&meta) {
stats.skip += 1; results.push(TestResult::skip(path.clone(), reason));
continue; stats.skip += 1;
continue;
}
} }
let result = run_test(path, &source, &meta, &kernel, &harness_module); let result = run_test(path, &source, &meta, &kernel, &harness_module, config.no_skip);
match &result.outcome { match &result.outcome {
TestOutcome::Pass(_) => stats.pass += 1, TestOutcome::Pass(_) => stats.pass += 1,
TestOutcome::Fail(msg) => { TestOutcome::Fail(msg) => {