From 91930760ae285a26acf86bf33cabd74b1f9501af Mon Sep 17 00:00:00 2001 From: naoNao89 <90588855+naoNao89@users.noreply.github.com> Date: Thu, 13 Nov 2025 02:27:58 +0700 Subject: [PATCH 1/2] benches: Port factor benchmarks from Criterion to Divan Replace Criterion with Divan to align with all other benchmarks in the codebase (22 packages use Divan, only factor used Criterion). Eliminates the html_reports warning and consolidates on a single benchmarking framework across the project. --- Cargo.lock | 149 ++------------------------ tests/benches/factor/Cargo.toml | 2 +- tests/benches/factor/benches/table.rs | 34 +++--- 3 files changed, 24 insertions(+), 161 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8c9f0c735..10c1e72c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -32,12 +32,6 @@ dependencies = [ "libc", ] -[[package]] -name = "anes" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" - [[package]] name = "ansi-width" version = "0.1.0" @@ -303,12 +297,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" -[[package]] -name = "cast" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" - [[package]] name = "cc" version = "1.2.27" @@ -350,33 +338,6 @@ dependencies = [ "windows-link 0.2.1", ] -[[package]] -name = "ciborium" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" -dependencies = [ - "ciborium-io", - "ciborium-ll", - "serde", -] - -[[package]] -name = "ciborium-io" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" - -[[package]] -name = "ciborium-ll" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" -dependencies = [ - "ciborium-io", - "half", -] - [[package]] name = "clang-sys" version = "1.8.1" @@ -762,39 +723,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "criterion" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bf7af66b0989381bd0be551bd7cc91912a655a58c6918420c9527b1fd8b4679" -dependencies = [ - "anes", - "cast", - "ciborium", - "clap", - "criterion-plot", - "itertools 0.13.0", - "num-traits", - "oorandom", - "plotters", - "rayon", - "regex", - "serde", - "serde_json", - "tinytemplate", - "walkdir", -] - -[[package]] -name = "criterion-plot" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" -dependencies = [ - "cast", - "itertools 0.10.5", -] - [[package]] name = "crossbeam-deque" version = "0.8.6" @@ -1619,15 +1547,6 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.13.0" @@ -1664,7 +1583,7 @@ dependencies = [ "portable-atomic", "portable-atomic-util", "serde_core", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1751,7 +1670,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.52.6", + "windows-targets 0.53.2", ] [[package]] @@ -1962,7 +1881,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2076,12 +1995,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "oorandom" -version = "11.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" - [[package]] name = "ordered-multimap" version = "0.7.3" @@ -2208,34 +2121,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "plotters" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" -dependencies = [ - "num-traits", - "plotters-backend", - "plotters-svg", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "plotters-backend" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" - -[[package]] -name = "plotters-svg" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" -dependencies = [ - "plotters-backend", -] - [[package]] name = "portable-atomic" version = "1.11.1" @@ -2567,7 +2452,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.11.0", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2867,7 +2752,7 @@ dependencies = [ "getrandom 0.3.3", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2984,16 +2869,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "tinytemplate" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" -dependencies = [ - "serde", - "serde_json", -] - [[package]] name = "toml_datetime" version = "0.6.11" @@ -3461,7 +3336,7 @@ name = "uu_factor_benches" version = "0.0.0" dependencies = [ "array-init", - "criterion", + "codspeed-divan-compat", "num-prime", "rand 0.9.2", "rand_chacha 0.9.0", @@ -4505,16 +4380,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "web-sys" -version = "0.3.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - [[package]] name = "web-time" version = "1.1.0" @@ -4556,7 +4421,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] diff --git a/tests/benches/factor/Cargo.toml b/tests/benches/factor/Cargo.toml index 30d4cc8b1..02e59925c 100644 --- a/tests/benches/factor/Cargo.toml +++ b/tests/benches/factor/Cargo.toml @@ -10,7 +10,7 @@ publish = false [dev-dependencies] array-init = "2.0.0" -criterion = "0.6.0" +divan = { workspace = true } rand = "0.9.1" rand_chacha = "0.9.0" num-prime = "0.4.4" diff --git a/tests/benches/factor/benches/table.rs b/tests/benches/factor/benches/table.rs index 504b7e8e3..4d89282fa 100644 --- a/tests/benches/factor/benches/table.rs +++ b/tests/benches/factor/benches/table.rs @@ -6,9 +6,14 @@ // spell-checker:ignore funcs use array_init::array_init; -use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_main}; +use divan::Bencher; -fn table(c: &mut Criterion) { +fn main() { + divan::main(); +} + +#[divan::bench()] +fn factor_table(bencher: Bencher) { #[cfg(target_os = "linux")] check_personality(); @@ -22,21 +27,17 @@ fn table(c: &mut Criterion) { let mut rng = ChaCha8Rng::seed_from_u64(SEED); std::iter::repeat_with(move || array_init::<_, _, INPUT_SIZE>(|_| rng.next_u64())) + .take(10) + .collect::>() }; - let mut group = c.benchmark_group("table"); - group.throughput(Throughput::Elements(INPUT_SIZE as _)); - for a in inputs.take(10) { - let a_str = format!("{a:?}"); - group.bench_with_input(BenchmarkId::new("factor", &a_str), &a, |b, &a| { - b.iter(|| { - for n in a { - let _r = num_prime::nt_funcs::factors(n, None); - } - }); - }); - } - group.finish(); + bencher.bench(|| { + for a in &inputs { + for n in a { + divan::black_box(num_prime::nt_funcs::factors(*n, None)); + } + } + }); } #[cfg(target_os = "linux")] @@ -59,6 +60,3 @@ fn check_personality() { ); } } - -criterion_group!(benches, table); -criterion_main!(benches); From e502d894dc6534f77b94f89abbec550b8dc6c892 Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Wed, 12 Nov 2025 16:18:18 +0100 Subject: [PATCH 2/2] test: existing file is newer than non-existing existing -nt non-existing => true non-existing -nt existing => false existing -ot non-existing => false non-existing -ot existing => true --- Cargo.lock | 1 + src/uu/test/Cargo.toml | 9 ++-- src/uu/test/src/test.rs | 107 +++++++++++++++++++++++++++++++------ tests/by-util/test_test.rs | 30 +++++++---- 4 files changed, 118 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f2f8412cc..fa3a3018e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4104,6 +4104,7 @@ dependencies = [ "clap", "fluent", "libc", + "tempfile", "thiserror 2.0.17", "uucore", ] diff --git a/src/uu/test/Cargo.toml b/src/uu/test/Cargo.toml index 1785063a0..3348efd7b 100644 --- a/src/uu/test/Cargo.toml +++ b/src/uu/test/Cargo.toml @@ -19,10 +19,13 @@ path = "src/test.rs" [dependencies] clap = { workspace = true } -libc = { workspace = true } -uucore = { workspace = true, features = ["process"] } -thiserror = { workspace = true } fluent = { workspace = true } +libc = { workspace = true } +thiserror = { workspace = true } +uucore = { workspace = true, features = ["process"] } + +[dev-dependencies] +tempfile = { workspace = true } [[bin]] name = "test" diff --git a/src/uu/test/src/test.rs b/src/uu/test/src/test.rs index 34d594241..0e4e809d7 100644 --- a/src/uu/test/src/test.rs +++ b/src/uu/test/src/test.rs @@ -205,24 +205,26 @@ fn integers(a: &OsStr, b: &OsStr, op: &OsStr) -> ParseResult { /// Operations to compare files metadata /// `a` is the left hand side -/// `b` is the left hand side +/// `b` is the right hand side /// `op` the operation (ex: -ef, -nt, etc) fn files(a: &OsStr, b: &OsStr, op: &OsStr) -> ParseResult { - // Don't manage the error. GNU doesn't show error when doing - // test foo -nt bar - let (Ok(f_a), Ok(f_b)) = (fs::metadata(a), fs::metadata(b)) else { - return Ok(false); + let f_a = fs::metadata(a); + let f_b = fs::metadata(b); + + let result = match (op.to_str(), f_a, f_b) { + #[cfg(unix)] + (Some("-ef"), Ok(f_a), Ok(f_b)) => f_a.ino() == f_b.ino() && f_a.dev() == f_b.dev(), + #[cfg(not(unix))] + (Some("-ef"), Ok(_), Ok(_)) => unimplemented!(), + (Some("-nt"), Ok(f_a), Ok(f_b)) => f_a.modified().unwrap() > f_b.modified().unwrap(), + (Some("-nt"), Ok(_), _) => true, + (Some("-ot"), Ok(f_a), Ok(f_b)) => f_a.modified().unwrap() < f_b.modified().unwrap(), + (Some("-ot"), _, Ok(_)) => true, + (Some("-ef" | "-nt" | "-ot"), _, _) => false, + (_, _, _) => return Err(ParseError::UnknownOperator(op.quote().to_string())), }; - Ok(match op.to_str() { - #[cfg(unix)] - Some("-ef") => f_a.ino() == f_b.ino() && f_a.dev() == f_b.dev(), - #[cfg(not(unix))] - Some("-ef") => unimplemented!(), - Some("-nt") => f_a.modified().unwrap() > f_b.modified().unwrap(), - Some("-ot") => f_a.modified().unwrap() < f_b.modified().unwrap(), - _ => return Err(ParseError::UnknownOperator(op.quote().to_string())), - }) + Ok(result) } fn isatty(fd: &OsStr) -> ParseResult { @@ -347,8 +349,81 @@ fn path(path: &OsStr, condition: &PathCondition) -> bool { #[cfg(test)] mod tests { - use super::integers; - use std::ffi::OsStr; + use super::*; + use std::{ffi::OsStr, time::UNIX_EPOCH}; + use tempfile::NamedTempFile; + + #[test] + fn test_files_with_unknown_op() { + let a = NamedTempFile::new().unwrap(); + let b = NamedTempFile::new().unwrap(); + let a = OsStr::new(a.path()); + let b = OsStr::new(b.path()); + let op = OsStr::new("unknown_op"); + + assert!(files(a, b, op).is_err()); + } + + #[test] + #[cfg(unix)] + fn test_files_with_ef_op() { + let a = NamedTempFile::new().unwrap(); + let b = NamedTempFile::new().unwrap(); + let a = OsStr::new(a.path()); + let b = OsStr::new(b.path()); + let op = OsStr::new("-ef"); + + assert!(files(a, a, op).unwrap()); + assert!(!files(a, b, op).unwrap()); + assert!(!files(b, a, op).unwrap()); + + let existing_file = a; + let non_existing_file = OsStr::new("non_existing_file"); + + assert!(!files(existing_file, non_existing_file, op).unwrap()); + assert!(!files(non_existing_file, existing_file, op).unwrap()); + assert!(!files(non_existing_file, non_existing_file, op).unwrap()); + } + + #[test] + fn test_files_with_nt_op() { + let older_file = NamedTempFile::new().unwrap(); + older_file.as_file().set_modified(UNIX_EPOCH).unwrap(); + let older_file = OsStr::new(older_file.path()); + let newer_file = NamedTempFile::new().unwrap(); + let newer_file = OsStr::new(newer_file.path()); + let op = OsStr::new("-nt"); + + assert!(files(newer_file, older_file, op).unwrap()); + assert!(!files(older_file, newer_file, op).unwrap()); + + let existing_file = newer_file; + let non_existing_file = OsStr::new("non_existing_file"); + + assert!(files(existing_file, non_existing_file, op).unwrap()); + assert!(!files(non_existing_file, existing_file, op).unwrap()); + assert!(!files(non_existing_file, non_existing_file, op).unwrap()); + } + + #[test] + fn test_files_with_ot_op() { + let older_file = NamedTempFile::new().unwrap(); + older_file.as_file().set_modified(UNIX_EPOCH).unwrap(); + let older_file = OsStr::new(older_file.path()); + let newer_file = NamedTempFile::new().unwrap(); + let newer_file = OsStr::new(newer_file.path()); + let op = OsStr::new("-ot"); + + assert!(!files(newer_file, older_file, op).unwrap()); + assert!(files(older_file, newer_file, op).unwrap()); + + let existing_file = newer_file; + let non_existing_file = OsStr::new("non_existing_file"); + + assert!(!files(existing_file, non_existing_file, op).unwrap()); + assert!(files(non_existing_file, existing_file, op).unwrap()); + assert!(!files(non_existing_file, non_existing_file, op).unwrap()); + } #[test] fn test_integer_op() { diff --git a/tests/by-util/test_test.rs b/tests/by-util/test_test.rs index 1dba782f5..4b5460cfd 100644 --- a/tests/by-util/test_test.rs +++ b/tests/by-util/test_test.rs @@ -5,10 +5,8 @@ // spell-checker:ignore (words) egid euid pseudofloat -use uutests::at_and_ucmd; -use uutests::new_ucmd; use uutests::util::TestScenario; -use uutests::util_name; +use uutests::{at_and_ucmd, new_ucmd, util_name}; #[test] fn test_empty_test_equivalent_to_false() { @@ -337,14 +335,26 @@ fn test_file_is_newer_than_and_older_than_itself() { } #[test] -fn test_non_existing_files() { - let scenario = TestScenario::new(util_name!()); +fn test_file_is_newer_than_non_existing_file() { + new_ucmd!() + .args(&["non_existing_file", "-nt", "regular_file"]) + .fails_with_code(1) + .no_output(); - let result = scenario - .ucmd() - .args(&["newer_file", "-nt", "regular_file"]) - .fails_with_code(1); - assert!(result.stderr().is_empty()); + new_ucmd!() + .args(&["regular_file", "-nt", "non_existing_file"]) + .succeeds() + .no_output(); + + new_ucmd!() + .args(&["non_existing_file", "-ot", "regular_file"]) + .succeeds() + .no_output(); + + new_ucmd!() + .args(&["regular_file", "-ot", "non_existing_file"]) + .fails_with_code(1) + .no_output(); } #[test]