mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-25 03:01:12 +08:00
fix: 修正 test262 runner 监督组合行为与安全默认值
This commit is contained in:
@@ -36,6 +36,12 @@ impl RunConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 监督模式判定:`--supervise` 且非监督派生的子进程(子进程不重入监督)。
|
||||||
|
/// 路径 filter 不参与判定——filter 在子进程内逐测试应用,不构成监督屏障。
|
||||||
|
pub(crate) fn supervised(&self, is_chunk_child: bool) -> bool {
|
||||||
|
self.supervise && !is_chunk_child
|
||||||
|
}
|
||||||
|
|
||||||
/// 解析命令行参数为运行配置;未知选项或参数过多返回错误。
|
/// 解析命令行参数为运行配置;未知选项或参数过多返回错误。
|
||||||
pub(crate) fn parse(args: &[String]) -> Result<Self, String> {
|
pub(crate) fn parse(args: &[String]) -> Result<Self, String> {
|
||||||
let mut config = Self::new();
|
let mut config = Self::new();
|
||||||
@@ -82,14 +88,26 @@ impl RunConfig {
|
|||||||
--no-fail-list Do not print the per-path FAIL list at the end of the run.\n\
|
--no-fail-list Do not print the per-path FAIL list at the end of the run.\n\
|
||||||
--supervise Run the suite as single-worker child-process windows with a hard per-test timeout and\n\
|
--supervise Run the suite as single-worker child-process windows with a hard per-test timeout and\n\
|
||||||
\x20 automatic resume past any hanging/crashing test. A hang or crash is reported by path.\n\
|
\x20 automatic resume past any hanging/crashing test. A hang or crash is reported by path.\n\
|
||||||
|
\x20 Combines with [path-filter]: the filter is applied per-test inside each child window.\n\
|
||||||
--leak-check Monitor session_object_ptrs, session_bytes, code_forge.len(), symbol_registry.len() every\n\
|
--leak-check Monitor session_object_ptrs, session_bytes, code_forge.len(), symbol_registry.len() every\n\
|
||||||
\x20 --leak-check-interval tests (default 1000). Flags sustained linear growth (R^2>0.9).\n\
|
\x20 --leak-check-interval tests (default 1000). Flags sustained linear growth (R^2>0.9).\n\
|
||||||
\n\
|
\n\
|
||||||
supervised-mode env tunables:\n\
|
env tunables (all optional):\n\
|
||||||
\x20 OXIDE_TEST262_TIMEOUT_SECS per-test wall-clock timeout (default 10)\n\
|
\x20 OXIDE_LOG per-subsystem log levels (default off)\n\
|
||||||
\x20 OXIDE_TEST262_WINDOW tests per window (default 5000)\n\
|
\x20 OXIDE_TEST262_WORKERS worker threads in parallel mode (default = available parallelism, 4 under --no-skip)\n\
|
||||||
\x20 OXIDE_TEST262_SUPERVISORS concurrent windows (default = available parallelism)\n\
|
\x20 OXIDE_TEST262_WINDOW supervised tests per child window (default 5000)\n\
|
||||||
\x20 OXIDE_TEST262_STARTUP_GRACE_SECS grace for a child's first heartbeat (default 60)"
|
\x20 OXIDE_TEST262_TIMEOUT_SECS per-test wall-clock timeout in supervised mode (default 10)\n\
|
||||||
|
\x20 OXIDE_TEST262_STARTUP_GRACE_SECS grace for a child's first heartbeat (default 60)\n\
|
||||||
|
\x20 OXIDE_TEST262_SUPERVISORS concurrent supervised windows (default 16)\n\
|
||||||
|
\x20 OXIDE_TEST262_RUNNING_LOG log every test as it starts (any value)\n\
|
||||||
|
\x20 OXIDE_TEST262_HEARTBEAT heartbeat file path (supervised/chunked)\n\
|
||||||
|
\x20 OXIDE_TEST262_CHUNK_SIZE tests per child in chunked mode\n\
|
||||||
|
\x20 OXIDE_TEST262_CHILD_CHUNK marks a spawned child as chunk worker (any value)\n\
|
||||||
|
\x20 OXIDE_TEST262_ALLOW_FAIL_EXIT child may exit 1 on fail (any value)\n\
|
||||||
|
\x20 OXIDE_TEST262_KERNEL_BATCH kernel rebuilds every N tests (default 5000, 1000 under --no-skip)\n\
|
||||||
|
\x20 OXIDE_TEST262_LOG_LEVEL runner log level (default info)\n\
|
||||||
|
\x20 OXIDE_SKIP_UNTIL skip test indexes below N (chunking/supervise resume)\n\
|
||||||
|
\x20 OXIDE_MAX_TESTS run at most N tests after skip point"
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -142,6 +160,18 @@ mod tests {
|
|||||||
assert_eq!(help, RunConfig::usage());
|
assert_eq!(help, RunConfig::usage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 监督判定三态:开启时 filter 不否决、子进程不重入、未开启恒 false。
|
||||||
|
#[test]
|
||||||
|
fn supervised_predicate_ignores_filter() {
|
||||||
|
let mut cfg = RunConfig::new();
|
||||||
|
cfg.supervise = true;
|
||||||
|
cfg.filter = Some("language".to_string());
|
||||||
|
assert!(cfg.supervised(false), "filter 不得否决监督");
|
||||||
|
assert!(!cfg.supervised(true), "子进程不得重入监督");
|
||||||
|
let off = RunConfig::new();
|
||||||
|
assert!(!off.supervised(false));
|
||||||
|
}
|
||||||
|
|
||||||
/// interval 非数字回落缺省 1000;位置参数超过 2 个返回错误。
|
/// interval 非数字回落缺省 1000;位置参数超过 2 个返回错误。
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_interval_fallback_and_positional_limit() {
|
fn parse_interval_fallback_and_positional_limit() {
|
||||||
|
|||||||
@@ -69,6 +69,11 @@ fn print_fail_categories(stats: &RunStats, paths: &[PathBuf]) {
|
|||||||
/// 汇总并打印统计;任何失败使返回值为 false(进程退出码 1)。
|
/// 汇总并打印统计;任何失败使返回值为 false(进程退出码 1)。
|
||||||
fn run_tests() -> bool {
|
fn run_tests() -> bool {
|
||||||
let args: Vec<String> = std::env::args().collect();
|
let args: Vec<String> = std::env::args().collect();
|
||||||
|
// 帮助走 stdout 并成功退出,与错误路径(stderr + 退出码 1)分离。
|
||||||
|
if args.iter().any(|a| a == "--help" || a == "-h") {
|
||||||
|
println!("{}", RunConfig::usage());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
let config = match RunConfig::parse(&args) {
|
let config = match RunConfig::parse(&args) {
|
||||||
Ok(config) => config,
|
Ok(config) => config,
|
||||||
Err(msg) => {
|
Err(msg) => {
|
||||||
@@ -147,9 +152,6 @@ fn run_tests() -> bool {
|
|||||||
let log_running_tests = std::env::var_os("OXIDE_TEST262_RUNNING_LOG").is_some();
|
let log_running_tests = std::env::var_os("OXIDE_TEST262_RUNNING_LOG").is_some();
|
||||||
let heartbeat_path: Option<PathBuf> = std::env::var_os("OXIDE_TEST262_HEARTBEAT").map(PathBuf::from);
|
let heartbeat_path: Option<PathBuf> = std::env::var_os("OXIDE_TEST262_HEARTBEAT").map(PathBuf::from);
|
||||||
|
|
||||||
test262_info!("running on {} worker thread(s)", workers);
|
|
||||||
eprintln!("running on {workers} worker thread(s)");
|
|
||||||
|
|
||||||
let skip_until = std::env::var("OXIDE_SKIP_UNTIL")
|
let skip_until = std::env::var("OXIDE_SKIP_UNTIL")
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|s| s.parse::<usize>().ok())
|
.and_then(|s| s.parse::<usize>().ok())
|
||||||
@@ -173,7 +175,7 @@ fn run_tests() -> bool {
|
|||||||
let is_chunk_child = std::env::var_os("OXIDE_TEST262_CHILD_CHUNK").is_some();
|
let is_chunk_child = std::env::var_os("OXIDE_TEST262_CHILD_CHUNK").is_some();
|
||||||
let allow_fail_exit = std::env::var_os("OXIDE_TEST262_ALLOW_FAIL_EXIT").is_some();
|
let allow_fail_exit = std::env::var_os("OXIDE_TEST262_ALLOW_FAIL_EXIT").is_some();
|
||||||
|
|
||||||
if config.supervise && !is_chunk_child && filter.is_none() {
|
if config.supervised(is_chunk_child) {
|
||||||
test262_info!("supervised mode enabled");
|
test262_info!("supervised mode enabled");
|
||||||
eprintln!("supervised mode enabled: child-window execution with per-test timeout + auto-resume");
|
eprintln!("supervised mode enabled: child-window execution with per-test timeout + auto-resume");
|
||||||
return run_supervised(&args, skip_until, end_index, config.no_skip, &paths);
|
return run_supervised(&args, skip_until, end_index, config.no_skip, &paths);
|
||||||
@@ -186,6 +188,9 @@ fn run_tests() -> bool {
|
|||||||
return run_chunked(&args, skip_until, end_index, chunk_size);
|
return run_chunked(&args, skip_until, end_index, chunk_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 并行模式专属:监督/分块模式在此前已返回,不派生 worker 线程。
|
||||||
|
test262_info!("running on {} worker thread(s)", workers);
|
||||||
|
eprintln!("running on {workers} worker thread(s)");
|
||||||
test262_info!("kernel reset batch: {} test(s)", kernel_batch);
|
test262_info!("kernel reset batch: {} test(s)", kernel_batch);
|
||||||
eprintln!("kernel reset batch: {kernel_batch} test(s)");
|
eprintln!("kernel reset batch: {kernel_batch} test(s)");
|
||||||
let cursor = AtomicUsize::new(skip_until);
|
let cursor = AtomicUsize::new(skip_until);
|
||||||
|
|||||||
@@ -248,11 +248,12 @@ pub(crate) fn run_supervised(
|
|||||||
id += 1;
|
id += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 缺省 16:全量复测验证过的安全并发;未经复测不得抬高。
|
||||||
let supervisors = std::env::var("OXIDE_TEST262_SUPERVISORS")
|
let supervisors = std::env::var("OXIDE_TEST262_SUPERVISORS")
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|s| s.parse::<usize>().ok())
|
.and_then(|s| s.parse::<usize>().ok())
|
||||||
.filter(|&n| n > 0)
|
.filter(|&n| n > 0)
|
||||||
.unwrap_or_else(|| std::thread::available_parallelism().map(|n| n.get()).unwrap_or(4))
|
.unwrap_or(16)
|
||||||
.min(windows.len().max(1));
|
.min(windows.len().max(1));
|
||||||
|
|
||||||
eprintln!(
|
eprintln!(
|
||||||
|
|||||||
Reference in New Issue
Block a user