diff --git a/.github/workflows/wasi.yml b/.github/workflows/wasi.yml index 5072ccc573b..0359c508473 100644 --- a/.github/workflows/wasi.yml +++ b/.github/workflows/wasi.yml @@ -60,7 +60,7 @@ jobs: # Tests incompatible with WASI are annotated with # #[cfg_attr(wasi_runner, ignore)] in the test source files. # TODO: add integration tests for these tools as WASI support is extended: - # arch b2sum cat cksum cp csplit date dir dircolors fmt join + # arch b2sum cat cksum csplit date dir dircolors fmt join # ls md5sum mkdir mv nproc pathchk pr printenv ptx pwd readlink # realpath rm rmdir seq sha1sum sha224sum sha256sum sha384sum # sha512sum shred sleep sort split tail touch tsort uname uniq @@ -69,7 +69,7 @@ jobs: UUTESTS_WASM_RUNNER=wasmtime \ cargo test --test tests -- \ test_base32:: test_base64:: test_basenc:: test_basename:: \ - test_comm:: test_cut:: test_dirname:: test_echo:: \ + test_comm:: test_cp:: test_cut:: test_dirname:: test_echo:: \ test_expand:: test_factor:: test_false:: test_fold:: \ test_head:: test_link:: test_ln:: test_nl:: test_numfmt:: \ test_od:: test_paste:: test_printf:: test_shuf:: test_sum:: \ diff --git a/Cargo.toml b/Cargo.toml index 7bf799b1763..0b7730677d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -523,6 +523,7 @@ unexpected_cfgs = { level = "warn", check-cfg = [ 'cfg(fuzzing)', 'cfg(target_os, values("cygwin"))', 'cfg(wasi_runner)', + 'cfg(wasip2_runner)', ] } unused_qualifications = "warn" diff --git a/src/uu/sort/src/check.rs b/src/uu/sort/src/check.rs index a826bc75507..f161426bd79 100644 --- a/src/uu/sort/src/check.rs +++ b/src/uu/sort/src/check.rs @@ -11,9 +11,9 @@ use crate::{ compare_by, open, }; use itertools::Itertools; +use std::{cmp::Ordering, ffi::OsStr}; +#[cfg(not(target_os = "wasi"))] use std::{ - cmp::Ordering, - ffi::OsStr, io::Read, iter, sync::mpsc::{Receiver, SyncSender, sync_channel}, @@ -21,11 +21,78 @@ use std::{ }; use uucore::error::UResult; +fn buffer_size(settings: &GlobalSettings) -> usize { + if settings.buffer_size < 100 * 1024 { + // when the buffer size is smaller than 100KiB we choose it instead of the default. + // this improves testability. + settings.buffer_size + } else { + 100 * 1024 + } +} + +/// Given the chunks of a file (in order), find the first pair of adjacent +/// lines that violates the requested ordering and report it as a +/// [`SortError::Disorder`]. +#[cfg(target_os = "wasi")] +fn check_chunks( + path: &OsStr, + settings: &GlobalSettings, + max_allowed_cmp: Ordering, + chunks: impl Iterator, +) -> UResult<()> { + let mut prev_chunk: Option = None; + let mut line_idx = 0; + for chunk in chunks { + line_idx += 1; + if let Some(prev_chunk) = &prev_chunk { + // Check if the first element of the new chunk is greater than the last + // element from the previous chunk + let prev_last = prev_chunk.lines().last().unwrap(); + let new_first = chunk.lines().first().unwrap(); + + if compare_by( + prev_last, + new_first, + settings, + prev_chunk.line_data(), + chunk.line_data(), + ) > max_allowed_cmp + { + return Err(SortError::Disorder { + file: path.to_owned(), + line_number: line_idx, + line: String::from_utf8_lossy(new_first.line).into_owned(), + silent: settings.check_silent, + } + .into()); + } + } + + for (a, b) in chunk.lines().iter().tuple_windows() { + line_idx += 1; + if compare_by(a, b, settings, chunk.line_data(), chunk.line_data()) > max_allowed_cmp { + return Err(SortError::Disorder { + file: path.to_owned(), + line_number: line_idx, + line: String::from_utf8_lossy(b.line).into_owned(), + silent: settings.check_silent, + } + .into()); + } + } + + prev_chunk = Some(chunk); + } + Ok(()) +} + /// Check if the file at `path` is ordered. /// /// # Returns /// /// The code we should exit with. +#[cfg(not(target_os = "wasi"))] pub fn check(path: &OsStr, settings: &GlobalSettings) -> UResult<()> { let max_allowed_cmp = if settings.unique { // If `unique` is enabled, the previous line must compare _less_ to the next one. @@ -42,13 +109,7 @@ pub fn check(path: &OsStr, settings: &GlobalSettings) -> UResult<()> { move || reader(file, &recycled_receiver, &loaded_sender, &settings) }); for _ in 0..2 { - let _ = recycled_sender.send(RecycledChunk::new(if settings.buffer_size < 100 * 1024 { - // when the buffer size is smaller than 100KiB we choose it instead of the default. - // this improves testability. - settings.buffer_size - } else { - 100 * 1024 - })); + let _ = recycled_sender.send(RecycledChunk::new(buffer_size(settings))); } let mut prev_chunk: Option = None; @@ -114,7 +175,27 @@ pub fn check(path: &OsStr, settings: &GlobalSettings) -> UResult<()> { result } +/// Check if the file at `path` is ordered. +/// +/// WASI has no thread support, so this reads every chunk up front on the +/// current thread instead of streaming them from a background reader thread. +/// +/// # Returns +/// +/// The code we should exit with. +#[cfg(target_os = "wasi")] +pub fn check(path: &OsStr, settings: &GlobalSettings) -> UResult<()> { + let max_allowed_cmp = if settings.unique { + Ordering::Less + } else { + Ordering::Equal + }; + let chunks = read_all_chunks(path, settings)?; + check_chunks(path, settings, max_allowed_cmp, chunks.into_iter()) +} + /// The function running on the reader thread. +#[cfg(not(target_os = "wasi"))] fn reader( mut file: Box, receiver: &Receiver, @@ -139,3 +220,33 @@ fn reader( } Ok(()) } + +/// Read every chunk of `path` up front, without any recycling or background +/// thread. Used on WASI, which has no thread support. +#[cfg(target_os = "wasi")] +fn read_all_chunks(path: &OsStr, settings: &GlobalSettings) -> UResult> { + let mut file = open(path)?; + let mut carry_over = vec![]; + let mut chunks = Vec::new(); + let (sender, receiver) = std::sync::mpsc::sync_channel(1); + loop { + let recycled = RecycledChunk::new(buffer_size(settings)); + let should_continue = chunks::read( + &sender, + recycled, + None, + &mut carry_over, + &mut file, + &mut std::iter::empty(), + settings.line_ending.into(), + settings, + )?; + while let Ok(chunk) = receiver.try_recv() { + chunks.push(chunk); + } + if !should_continue { + break; + } + } + Ok(chunks) +} diff --git a/src/uu/sort/src/ext_sort/wasi.rs b/src/uu/sort/src/ext_sort/wasi.rs index 50bd5f63033..d37c1f41cec 100644 --- a/src/uu/sort/src/ext_sort/wasi.rs +++ b/src/uu/sort/src/ext_sort/wasi.rs @@ -31,6 +31,13 @@ pub fn ext_sort( // moderately sized inputs; very large files may cause OOM. let mut input = Vec::new(); for file in files { + // Insert the separator between files whose preceding content doesn't + // already end with one; otherwise the last line of one file would + // merge with the first line of the next, e.g. "a\nb" + "b" -> + // "a\nbb" instead of "a\nb" + '\n' + "b". + if !input.is_empty() && input.last() != Some(&separator) { + input.push(separator); + } file?.read_to_end(&mut input)?; } if input.is_empty() { diff --git a/tests/by-util/test_cp.rs b/tests/by-util/test_cp.rs index 9ad4ef75c4d..10514b54917 100644 --- a/tests/by-util/test_cp.rs +++ b/tests/by-util/test_cp.rs @@ -95,6 +95,7 @@ macro_rules! assert_metadata_eq { #[test] #[cfg(target_os = "linux")] +#[cfg_attr(wasi_runner, ignore = "WASI sandbox: host paths not visible")] fn test_cp_stream_to_full() { let (_, mut ucmd) = at_and_ucmd!(); ucmd.arg("/dev/zero") @@ -105,6 +106,7 @@ fn test_cp_stream_to_full() { #[test] #[cfg(target_os = "linux")] +#[cfg_attr(wasip2_runner, ignore = "WASI P2: /dev/full filesystem not available")] fn test_cp_verbose_write_error_is_reported() { let (at, mut ucmd) = at_and_ucmd!(); at.touch("source_file"); @@ -313,6 +315,10 @@ fn test_cp_multiple_files_with_nonexistent_file() { } #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_multiple_files_with_empty_file_name() { #[cfg(windows)] let error_msg = "The system cannot find the path specified"; @@ -359,6 +365,7 @@ fn test_cp_recurse_several() { } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: directory copy with symlinks/metadata not fully supported")] fn test_cp_recurse_source_path_ends_with_slash_dot() { let source_dir = "source_dir"; let target_dir = "target_dir"; @@ -451,6 +458,7 @@ fn test_cp_arg_no_target_directory_with_recursive() { } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: directory copy with symlinks/metadata not fully supported")] fn test_cp_arg_no_target_directory_with_recursive_target_does_not_exists() { let (at, mut ucmd) = at_and_ucmd!(); @@ -803,6 +811,10 @@ fn test_cp_arg_interactive_verbose_clobber() { #[test] #[cfg(unix)] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_f_i_verbose_non_writeable_destination_y() { let (at, mut ucmd) = at_and_ucmd!(); @@ -821,6 +833,10 @@ fn test_cp_f_i_verbose_non_writeable_destination_y() { #[test] #[cfg(unix)] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_f_i_verbose_non_writeable_destination_empty() { let (at, mut ucmd) = at_and_ucmd!(); @@ -916,6 +932,7 @@ fn test_cp_verbose_preserved_link_to_dir() { } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_cp_arg_symlink() { let (at, mut ucmd) = at_and_ucmd!(); ucmd.arg(TEST_HELLO_WORLD_SOURCE) @@ -1049,6 +1066,7 @@ fn test_cp_arg_backup() { } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_cp_arg_backup_with_dest_a_symlink() { let (at, mut ucmd) = at_and_ucmd!(); let source = "source"; @@ -1070,6 +1088,7 @@ fn test_cp_arg_backup_with_dest_a_symlink() { } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_cp_arg_backup_with_dest_a_symlink_to_source() { let (at, mut ucmd) = at_and_ucmd!(); let source = "source"; @@ -1514,6 +1533,7 @@ fn test_cp_deref() { assert_eq!(at.read(path_to_check), "Hello, World!\n"); } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_cp_no_deref() { let (at, mut ucmd) = at_and_ucmd!(); @@ -1554,6 +1574,7 @@ fn test_cp_no_deref() { } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_cp_no_deref_link_onto_link() { let (at, mut ucmd) = at_and_ucmd!(); @@ -1665,6 +1686,10 @@ fn test_cp_parents_dest_not_directory() { #[test] #[cfg(not(target_os = "openbsd"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_parents_with_permissions_copy_file() { let (at, mut ucmd) = at_and_ucmd!(); @@ -1706,6 +1731,10 @@ fn test_cp_parents_with_permissions_copy_file() { #[test] #[cfg(not(target_os = "openbsd"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_parents_with_permissions_copy_dir() { let (at, mut ucmd) = at_and_ucmd!(); @@ -1749,12 +1778,20 @@ fn test_cp_parents_with_permissions_copy_dir() { #[test] #[cfg(unix)] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_writable_special_file_permissions() { new_ucmd!().arg("/dev/null").arg("/dev/zero").succeeds(); } #[test] #[cfg(unix)] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_issue_1665() { let (at, mut ucmd) = at_and_ucmd!(); ucmd.arg("/dev/null").arg("foo").succeeds(); @@ -1764,6 +1801,10 @@ fn test_cp_issue_1665() { #[test] #[cfg(not(target_os = "openbsd"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_preserve_no_args() { let (at, mut ucmd) = at_and_ucmd!(); let src_file = "a"; @@ -1792,6 +1833,10 @@ fn test_cp_preserve_no_args() { #[test] #[cfg(not(target_os = "openbsd"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_preserve_no_args_before_opts() { let (at, mut ucmd) = at_and_ucmd!(); let src_file = "a"; @@ -1819,6 +1864,10 @@ fn test_cp_preserve_no_args_before_opts() { } #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_preserve_all() { for argument in ["--preserve=all", "--preserve=al"] { let (at, mut ucmd) = at_and_ucmd!(); @@ -2003,6 +2052,11 @@ fn test_cp_preserve_links_case_1() { #[test] // android platform will causing stderr = cp: Permission denied (os error 13) #[cfg(not(target_os = "android"))] +#[cfg_attr( + wasip2_runner, + ignore = "WASI preview2: rustix::fs::stat doesn't return stable inode identity across path lookups (wasmtime filesystem limitation)" +)] +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_cp_preserve_links_case_2() { let (at, mut ucmd) = at_and_ucmd!(); @@ -2034,6 +2088,11 @@ fn test_cp_preserve_links_case_2() { #[test] // android platform will causing stderr = cp: Permission denied (os error 13) #[cfg(not(target_os = "android"))] +#[cfg_attr( + wasip2_runner, + ignore = "WASI preview2: rustix::fs::stat doesn't return stable inode identity across path lookups (wasmtime filesystem limitation)" +)] +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_cp_preserve_links_case_3() { let (at, mut ucmd) = at_and_ucmd!(); @@ -2174,6 +2233,7 @@ fn test_cp_preserve_links_case_7() { #[test] #[cfg(unix)] +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_cp_no_preserve_mode() { use uucore::fs as uufs; let (at, mut ucmd) = at_and_ucmd!(); @@ -2199,6 +2259,10 @@ fn test_cp_no_preserve_mode() { // For now, disable the test on Windows. Symlinks aren't well support on Windows. // It works on Unix for now and it works locally when run from a powershell #[cfg(not(windows))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_deref_folder_to_folder() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -2297,6 +2361,10 @@ fn test_cp_deref_folder_to_folder() { // For now, disable the test on Windows. Symlinks aren't well support on Windows. // It works on Unix for now and it works locally when run from a powershell #[cfg(not(windows))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_no_deref_folder_to_folder() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -2393,6 +2461,10 @@ fn test_cp_no_deref_folder_to_folder() { #[test] #[cfg(target_os = "linux")] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_archive() { let (at, mut ucmd) = at_and_ucmd!(); let ts = time::OffsetDateTime::now_utc(); @@ -2426,6 +2498,10 @@ fn test_cp_archive() { #[test] #[cfg(all(unix, not(target_os = "android")))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_archive_recursive() { let (at, mut ucmd) = at_and_ucmd!(); @@ -2568,6 +2644,7 @@ fn test_cp_no_preserve_timestamps() { #[test] #[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg_attr(wasi_runner, ignore = "WASI sandbox: host paths not visible")] fn test_cp_target_file_dev_null() { let (at, mut ucmd) = at_and_ucmd!(); let file1 = "/dev/null"; @@ -2657,6 +2734,7 @@ fn test_cp_reflink_always() { #[test] #[cfg(any(target_os = "linux", target_os = "android", target_os = "macos"))] +#[cfg_attr(wasi_runner, ignore = "WASI: reflink not supported in WASI")] fn test_cp_reflink_auto() { let (at, mut ucmd) = at_and_ucmd!(); ucmd.arg("--reflink=auto") @@ -2736,6 +2814,10 @@ fn test_cp_conflicting_update() { #[test] #[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_reflink_insufficient_permission() { let (at, mut ucmd) = at_and_ucmd!(); @@ -2753,6 +2835,7 @@ fn test_cp_reflink_insufficient_permission() { #[cfg(target_os = "linux")] #[test] +#[cfg_attr(wasi_runner, ignore = "WASI sandbox: host paths not visible")] fn test_closes_file_descriptors() { use rlimit::Resource; @@ -2780,6 +2863,10 @@ fn test_closes_file_descriptors() { #[cfg(any(target_os = "linux", target_os = "android"))] #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_sparse_never_empty() { const BUFFER_SIZE: usize = 4096 * 4; let (at, mut ucmd) = at_and_ucmd!(); @@ -2800,6 +2887,10 @@ fn test_cp_sparse_never_empty() { #[cfg(any(target_os = "linux", target_os = "android"))] #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_sparse_always_empty() { const BUFFER_SIZE: usize = 4096 * 4; for argument in ["--sparse=always", "--sparse=alway", "--sparse=al"] { @@ -2820,6 +2911,10 @@ fn test_cp_sparse_always_empty() { #[cfg(any(target_os = "linux", target_os = "android"))] #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_sparse_always_non_empty() { const BUFFER_SIZE: usize = 4096 * 16 + 3; let (at, mut ucmd) = at_and_ucmd!(); @@ -3051,6 +3146,10 @@ fn test_cp_debug_sparse_always_windows() { #[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(feature = "truncate")] #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_reflink_always_override() { const DISK: &str = "disk.img"; const ROOTDIR: &str = "disk_root/"; @@ -3130,6 +3229,7 @@ fn test_cp_reflink_always_override() { } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_copy_dir_symlink() { let (at, mut ucmd) = at_and_ucmd!(); at.mkdir("dir"); @@ -3141,6 +3241,10 @@ fn test_copy_dir_symlink() { #[test] #[cfg(not(target_os = "freebsd"))] // FIXME: fix this test for FreeBSD #[cfg(feature = "ln")] +#[cfg_attr( + wasi_runner, + ignore = "WASI sandbox: cross-scenario absolute host path not visible" +)] fn test_copy_dir_with_symlinks() { let (at, mut ucmd) = at_and_ucmd!(); at.mkdir("dir"); @@ -3159,6 +3263,7 @@ fn test_copy_dir_with_symlinks() { #[test] #[cfg(not(windows))] +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_copy_symlink_force() { let (at, mut ucmd) = at_and_ucmd!(); at.touch("file"); @@ -3173,6 +3278,10 @@ fn test_copy_symlink_force() { #[test] #[cfg(unix)] #[cfg(not(target_os = "openbsd"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_no_preserve_mode() { use std::os::unix::prelude::MetadataExt; @@ -3203,6 +3312,10 @@ fn test_no_preserve_mode() { #[test] #[cfg(unix)] #[cfg(not(target_os = "openbsd"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_preserve_mode() { use std::os::unix::prelude::MetadataExt; @@ -3237,6 +3350,7 @@ fn test_canonicalize_symlink() { } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_copy_through_just_created_symlink() { for create_t in [true, false] { let (at, mut ucmd) = at_and_ucmd!(); @@ -3276,6 +3390,7 @@ fn test_copy_through_dangling_symlink() { } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_copy_through_dangling_symlink_posixly_correct() { let (at, mut ucmd) = at_and_ucmd!(); at.touch("file"); @@ -3291,6 +3406,7 @@ fn test_copy_through_dangling_symlink_posixly_correct() { } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_copy_through_dangling_symlink_no_dereference() { let (at, mut ucmd) = at_and_ucmd!(); at.symlink_file("no-such-file", "dangle"); @@ -3302,6 +3418,7 @@ fn test_copy_through_dangling_symlink_no_dereference() { } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_cp_symlink_overwrite_detection() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; @@ -3358,6 +3475,10 @@ fn test_cp_dangling_symlink_inside_directory() { /// Test for copying a dangling symbolic link and its permissions. #[cfg(not(any(target_os = "freebsd", target_os = "openbsd")))] // FIXME: fix this test for FreeBSD/OpenBSD #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_copy_through_dangling_symlink_no_dereference_permissions() { let (at, mut ucmd) = at_and_ucmd!(); // target name link name @@ -3436,6 +3557,10 @@ fn test_cp_link_backup() { #[test] #[cfg(unix)] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_fifo() { let (at, mut ucmd) = at_and_ucmd!(); at.mkfifo("fifo"); @@ -3456,6 +3581,10 @@ fn test_cp_fifo() { #[test] #[cfg(unix)] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_fifo_preserve_timestamps() { // Preserving timestamps must not open the FIFO: opening a FIFO with no // writer blocks forever. If this regresses, the test hangs instead of @@ -3515,6 +3644,10 @@ fn test_cp_recursive_char_device(#[case] flag: &str) { #[case::recursive("-R")] #[case::archive("-a")] #[cfg(unix)] +#[cfg_attr( + wasi_runner, + ignore = "WASI sandbox: host paths (/dev/null) not visible" +)] fn test_cp_recursive_char_device_no_permission(#[case] flag: &str) { new_ucmd!() .args(&[flag, "/dev/null", "null2"]) @@ -3524,6 +3657,10 @@ fn test_cp_recursive_char_device_no_permission(#[case] flag: &str) { #[test] #[cfg(unix)] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_recursive_char_device_copy_contents() { let (at, mut ucmd) = at_and_ucmd!(); ucmd.args(&["-R", "--copy-contents", "/dev/null", "null2"]) @@ -3535,6 +3672,10 @@ fn test_cp_recursive_char_device_copy_contents() { #[test] #[cfg(unix)] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_char_device() { let (at, mut ucmd) = at_and_ucmd!(); ucmd.args(&["/dev/null", "null2"]).succeeds().no_stderr(); @@ -3601,6 +3742,10 @@ fn test_cp_block_device_no_permission() { #[test] #[cfg(unix)] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_socket() { let (at, mut ucmd) = at_and_ucmd!(); at.mksocket("socket"); @@ -3635,6 +3780,10 @@ fn find_other_group(_current: u32) -> Option { #[test] #[cfg(unix)] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_r_symlink() { let (at, mut ucmd) = at_and_ucmd!(); // Specifically test copying a link in a subdirectory, as the internal path @@ -3739,6 +3888,7 @@ fn test_cp_dir_vs_file() { } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_cp_overriding_arguments() { let s = TestScenario::new(util_name!()); s.fixtures.touch("file1"); @@ -3765,6 +3915,10 @@ fn test_cp_overriding_arguments() { } #[test] +#[cfg_attr( + wasip2_runner, + ignore = "WASI preview2: rustix::fs::stat doesn't return stable inode identity across path lookups (wasmtime filesystem limitation)" +)] fn test_copy_no_dereference_1() { let (at, mut ucmd) = at_and_ucmd!(); at.mkdir("a"); @@ -3775,6 +3929,7 @@ fn test_copy_no_dereference_1() { } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_abuse_existing() { let (at, mut ucmd) = at_and_ucmd!(); at.mkdir("a"); @@ -3794,6 +3949,7 @@ fn test_abuse_existing() { } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_copy_same_symlink_no_dereference() { let (at, mut ucmd) = at_and_ucmd!(); at.relative_symlink_file("t", "a"); @@ -3803,6 +3959,7 @@ fn test_copy_same_symlink_no_dereference() { } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_copy_same_symlink_no_dereference_dangling() { let (at, mut ucmd) = at_and_ucmd!(); at.relative_symlink_file("t", "a"); @@ -3813,6 +3970,10 @@ fn test_copy_same_symlink_no_dereference_dangling() { // TODO: enable for Android, when #3477 solved #[cfg(not(any(windows, target_os = "android", target_os = "openbsd")))] #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_parents_2_dirs() { let (at, mut ucmd) = at_and_ucmd!(); at.mkdir_all("a/b/c"); @@ -3859,6 +4020,7 @@ fn test_cp_parents_2_link() { } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: directory copy with symlinks/metadata not fully supported")] fn test_cp_parents_2_dir() { let (at, mut ucmd) = at_and_ucmd!(); at.mkdir_all("a/b/c"); @@ -3874,6 +4036,7 @@ fn test_cp_parents_2_dir() { } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: directory copy with symlinks/metadata not fully supported")] fn test_cp_parents_2_deep_dir() { let (at, mut ucmd) = at_and_ucmd!(); at.mkdir_all("a/b/c"); @@ -3906,6 +4069,7 @@ fn test_cp_parents_recursive_source_ending_in_parent_dir() { } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: directory copy with symlinks/metadata not fully supported")] fn test_cp_copy_symlink_contents_recursive() { let (at, mut ucmd) = at_and_ucmd!(); at.mkdir("src-dir"); @@ -3924,6 +4088,7 @@ fn test_cp_copy_symlink_contents_recursive() { } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_cp_mode_symlink() { for from in ["file", "slink", "slink2"] { let (at, mut ucmd) = at_and_ucmd!(); @@ -3969,6 +4134,7 @@ fn test_cp_mode_hardlink_no_dereference() { #[cfg(not(any(windows, target_os = "android")))] #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_remove_destination_with_destination_being_a_hardlink_to_source() { let (at, mut ucmd) = at_and_ucmd!(); let file = "file"; @@ -4030,6 +4196,7 @@ fn test_remove_destination_symbolic_link_loop() { #[test] #[cfg(not(windows))] +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_cp_symbolic_link_loop() { let (at, mut ucmd) = at_and_ucmd!(); at.symlink_file("loop", "loop"); @@ -4070,6 +4237,10 @@ fn test_copy_nested_directory_to_itself_disallowed() { /// Test for preserving permissions when copying a directory. #[cfg(all(not(windows), not(target_os = "freebsd"), not(target_os = "openbsd")))] #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_copy_dir_preserve_permissions() { // Create a directory that has some non-default permissions. let (at, mut ucmd) = at_and_ucmd!(); @@ -4096,6 +4267,10 @@ fn test_copy_dir_preserve_permissions() { /// cp should preserve attributes of subdirectories when copying recursively. #[cfg(all(not(windows), not(target_os = "freebsd"), not(target_os = "openbsd")))] #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_copy_dir_preserve_subdir_permissions() { let (at, mut ucmd) = at_and_ucmd!(); at.mkdir("a1"); @@ -4118,6 +4293,10 @@ fn test_copy_dir_preserve_subdir_permissions() { /// read-only mode, causing EPERM when copying files into it. #[cfg(all(not(windows), not(target_os = "freebsd"), not(target_os = "openbsd")))] #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_copy_dir_preserve_readonly_source_with_files() { let (at, mut ucmd) = at_and_ucmd!(); at.mkdir("src"); @@ -4137,6 +4316,10 @@ fn test_copy_dir_preserve_readonly_source_with_files() { /// the face of an inaccessible file in that directory. #[cfg(all(not(windows), not(target_os = "freebsd"), not(target_os = "openbsd")))] #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_copy_dir_preserve_permissions_inaccessible_file() { // Create a directory that has some non-default permissions and // contains an inaccessible file. @@ -4193,6 +4376,10 @@ fn test_same_file_force() { /// Test that copying file to itself with forced backup succeeds. #[cfg(not(windows))] #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_same_file_force_backup() { let (at, mut ucmd) = at_and_ucmd!(); at.touch("f"); @@ -4205,6 +4392,10 @@ fn test_same_file_force_backup() { /// Test for copying the contents of a FIFO as opposed to the FIFO object itself. #[cfg(unix)] #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_copy_contents_fifo() { let scenario = TestScenario::new(util_name!()); let at = &scenario.fixtures; @@ -4230,6 +4421,10 @@ fn test_copy_contents_fifo() { #[cfg(target_os = "linux")] #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_reflink_never_sparse_always() { let (at, mut ucmd) = at_and_ucmd!(); @@ -4257,6 +4452,10 @@ fn test_reflink_never_sparse_always() { /// Test for preserving attributes of a hard link in a directory. #[test] #[cfg(not(any(target_os = "android", target_os = "openbsd")))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_preserve_hardlink_attributes_in_directory() { let (at, mut ucmd) = at_and_ucmd!(); @@ -4299,6 +4498,7 @@ fn test_hard_link_file() { #[test] #[cfg(not(windows))] +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_symbolic_link_file() { let (at, mut ucmd) = at_and_ucmd!(); at.touch("src"); @@ -4313,6 +4513,10 @@ fn test_symbolic_link_file() { } #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_src_base_dot() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; @@ -4336,6 +4540,7 @@ fn non_utf8_name(suffix: &str) -> OsString { #[cfg(target_os = "linux")] #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: argv/filenames must be valid UTF-8")] fn test_non_utf8_src() { let (at, mut ucmd) = at_and_ucmd!(); let src = non_utf8_name("src"); @@ -4346,6 +4551,7 @@ fn test_non_utf8_src() { #[cfg(target_os = "linux")] #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: argv/filenames must be valid UTF-8")] fn test_non_utf8_dest() { let (at, mut ucmd) = at_and_ucmd!(); let dest = non_utf8_name("dest"); @@ -4357,6 +4563,7 @@ fn test_non_utf8_dest() { #[cfg(target_os = "linux")] #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: argv/filenames must be valid UTF-8")] fn test_non_utf8_target() { let (at, mut ucmd) = at_and_ucmd!(); let dest = non_utf8_name("dest"); @@ -4371,6 +4578,10 @@ fn test_non_utf8_target() { #[test] #[cfg(not(windows))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_archive_on_directory_ending_dot() { let (at, mut ucmd) = at_and_ucmd!(); at.mkdir("dir1"); @@ -4382,6 +4593,10 @@ fn test_cp_archive_on_directory_ending_dot() { #[test] #[cfg(any(target_os = "linux", target_os = "windows", target_os = "macos"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_debug_default() { #[cfg(target_os = "macos")] let expected = "copy offload: unknown, reflink: unsupported, sparse detection: unsupported"; @@ -4404,6 +4619,10 @@ fn test_cp_debug_default() { #[test] #[cfg(any(target_os = "linux", target_os = "windows", target_os = "macos"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_debug_multiple_default() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; @@ -4433,6 +4652,10 @@ fn test_cp_debug_multiple_default() { #[test] #[cfg(target_os = "linux")] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_debug_sparse_reflink() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; @@ -4465,6 +4688,10 @@ fn test_cp_debug_no_update() { #[test] #[cfg(target_os = "linux")] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_debug_sparse_always() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; @@ -4481,6 +4708,10 @@ fn test_cp_debug_sparse_always() { #[test] #[cfg(target_os = "linux")] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_debug_sparse_never() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; @@ -4496,6 +4727,10 @@ fn test_cp_debug_sparse_never() { } #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_debug_sparse_auto() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; @@ -4528,6 +4763,10 @@ fn test_cp_debug_sparse_auto() { #[test] #[cfg(any(target_os = "linux", target_os = "macos"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_debug_reflink_auto() { #[cfg(target_os = "macos")] let expected = "copy offload: unknown, reflink: unsupported, sparse detection: unsupported"; @@ -4549,6 +4788,10 @@ fn test_cp_debug_reflink_auto() { #[test] #[cfg(target_os = "linux")] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_debug_sparse_always_reflink_auto() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; @@ -4593,6 +4836,10 @@ fn test_cp_dest_no_permissions() { /// Test readonly destination behavior with reflink options #[cfg(any(target_os = "linux", target_os = "macos"))] #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_readonly_dest_with_reflink() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; @@ -4736,6 +4983,10 @@ fn test_cp_attributes_only_dest_open_error() { #[test] #[cfg(unix)] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_cannot_create_regular_file() { let (at, mut ucmd) = at_and_ucmd!(); at.write("source.txt", "hello"); @@ -4747,6 +4998,10 @@ fn test_cp_cannot_create_regular_file() { #[test] #[cfg(unix)] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_cannot_create_regular_file_attributes_only() { let (at, mut ucmd) = at_and_ucmd!(); at.write("source.txt", "hello"); @@ -4817,6 +5072,10 @@ fn test_cp_no_such() { not(any(target_os = "android", target_os = "macos", target_os = "openbsd")) ))] #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_acl_preserve() { use std::process::Command; @@ -4857,6 +5116,10 @@ fn test_acl_preserve() { #[test] #[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_debug_reflink_never_with_hole() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; @@ -4882,6 +5145,10 @@ fn test_cp_debug_reflink_never_with_hole() { #[test] #[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_debug_reflink_never_empty_file_with_hole() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; @@ -4907,6 +5174,10 @@ fn test_cp_debug_reflink_never_empty_file_with_hole() { #[test] #[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_debug_default_with_hole() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; @@ -4933,6 +5204,10 @@ fn test_cp_debug_default_with_hole() { #[test] #[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_debug_default_less_than_512_bytes() { let ts = TestScenario::new(util_name!()); @@ -4956,6 +5231,10 @@ fn test_cp_debug_default_less_than_512_bytes() { #[test] #[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_debug_default_without_hole() { let ts = TestScenario::new(util_name!()); @@ -4976,6 +5255,10 @@ fn test_cp_debug_default_without_hole() { #[test] #[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_debug_default_empty_file_with_hole() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; @@ -5002,6 +5285,10 @@ fn test_cp_debug_default_empty_file_with_hole() { #[test] #[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_debug_reflink_never_sparse_always_with_hole() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; @@ -5028,6 +5315,10 @@ fn test_cp_debug_reflink_never_sparse_always_with_hole() { #[test] #[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_debug_reflink_never_sparse_always_without_hole() { let ts = TestScenario::new(util_name!()); let empty_bytes = [0_u8; 10000]; @@ -5053,6 +5344,10 @@ fn test_cp_debug_reflink_never_sparse_always_without_hole() { #[test] #[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_debug_reflink_never_sparse_always_empty_file_with_hole() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; @@ -5075,6 +5370,10 @@ fn test_cp_debug_reflink_never_sparse_always_empty_file_with_hole() { #[test] #[cfg(target_os = "linux")] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_default_virtual_file() { // This file has existed at least since 2008, so we assume that it is present on "all" Linux kernels. // https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-profiling @@ -5098,6 +5397,10 @@ fn test_cp_default_virtual_file() { } #[test] #[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_debug_reflink_auto_sparse_always_non_sparse_file_with_long_zero_sequence() { let ts = TestScenario::new(util_name!()); @@ -5124,6 +5427,10 @@ fn test_cp_debug_reflink_auto_sparse_always_non_sparse_file_with_long_zero_seque #[test] #[cfg(target_os = "linux")] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_debug_sparse_never_empty_sparse_file() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; @@ -5140,6 +5447,10 @@ fn test_cp_debug_sparse_never_empty_sparse_file() { #[test] #[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_debug_reflink_never_sparse_always_non_sparse_file_with_long_zero_sequence() { let ts = TestScenario::new(util_name!()); @@ -5167,6 +5478,10 @@ fn test_cp_debug_reflink_never_sparse_always_non_sparse_file_with_long_zero_sequ #[test] #[cfg(target_os = "linux")] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_debug_sparse_always_sparse_virtual_file() { // This file has existed at least since 2008, so we assume that it is present on "all" Linux kernels. // https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-profiling @@ -5191,6 +5506,10 @@ fn test_cp_debug_sparse_always_sparse_virtual_file() { #[test] #[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_debug_reflink_never_less_than_512_bytes() { let ts = TestScenario::new(util_name!()); @@ -5213,6 +5532,10 @@ fn test_cp_debug_reflink_never_less_than_512_bytes() { #[test] #[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_debug_reflink_never_sparse_never_empty_file_with_hole() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; @@ -5235,6 +5558,10 @@ fn test_cp_debug_reflink_never_sparse_never_empty_file_with_hole() { #[test] #[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_debug_reflink_never_file_with_hole() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; @@ -5258,6 +5585,10 @@ fn test_cp_debug_reflink_never_file_with_hole() { #[test] #[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_debug_sparse_never_less_than_512_bytes() { let ts = TestScenario::new(util_name!()); @@ -5281,6 +5612,10 @@ fn test_cp_debug_sparse_never_less_than_512_bytes() { #[test] #[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_debug_sparse_never_without_hole() { let ts = TestScenario::new(util_name!()); @@ -5303,6 +5638,10 @@ fn test_cp_debug_sparse_never_without_hole() { #[test] #[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_debug_sparse_never_empty_file_with_hole() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; @@ -5325,6 +5664,10 @@ fn test_cp_debug_sparse_never_empty_file_with_hole() { #[test] #[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_debug_sparse_never_file_with_hole() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; @@ -5348,6 +5691,10 @@ fn test_cp_debug_sparse_never_file_with_hole() { #[test] #[cfg(target_os = "linux")] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_debug_default_sparse_virtual_file() { // This file has existed at least since 2008, so we assume that it is present on "all" Linux kernels. // https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-profiling @@ -5371,6 +5718,10 @@ fn test_cp_debug_default_sparse_virtual_file() { #[test] #[cfg(target_os = "linux")] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_debug_sparse_never_zero_sized_virtual_file() { let ts = TestScenario::new(util_name!()); ts.ucmd() @@ -5384,6 +5735,10 @@ fn test_cp_debug_sparse_never_zero_sized_virtual_file() { #[test] #[cfg(target_os = "linux")] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_debug_default_zero_sized_virtual_file() { let ts = TestScenario::new(util_name!()); ts.ucmd() @@ -5396,6 +5751,10 @@ fn test_cp_debug_default_zero_sized_virtual_file() { #[test] #[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_debug_reflink_never_without_hole() { let ts = TestScenario::new(util_name!()); let filler_bytes = [0_u8; 1000]; @@ -5413,6 +5772,10 @@ fn test_cp_debug_reflink_never_without_hole() { } #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_force_remove_destination_attributes_only_with_symlink() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -5482,6 +5845,11 @@ mod same_file { // the following tests tries to copy a file to the symlink of the same file with // various options #[test] + #[cfg_attr( + wasip2_runner, + ignore = "WASI preview2: rustix::fs::stat doesn't return stable inode identity across path lookups (wasmtime filesystem limitation)" + )] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_file_to_symlink() { for option in ["-d", "-f", "-df"] { let scene = TestScenario::new(util_name!()); @@ -5517,6 +5885,7 @@ mod same_file { } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_file_to_symlink_with_backup_option() { for option in ["-b", "-bd", "-bf", "-bdf"] { let scene = TestScenario::new(util_name!()); @@ -5538,6 +5907,7 @@ mod same_file { } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_file_to_symlink_with_link_option() { for option in ["-l", "-dl"] { let scene = TestScenario::new(util_name!()); @@ -5557,6 +5927,7 @@ mod same_file { } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_file_to_symlink_with_options_link_and_force() { for option in ["-fl", "-dfl"] { let scene = TestScenario::new(util_name!()); @@ -5574,6 +5945,7 @@ mod same_file { } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_file_to_symlink_with_options_backup_and_link() { for option in ["-bl", "-bdl", "-bfl", "-bdfl"] { let scene = TestScenario::new(util_name!()); @@ -5594,6 +5966,7 @@ mod same_file { } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_file_to_symlink_with_options_symlink() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -5611,6 +5984,7 @@ mod same_file { } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_file_to_symlink_with_options_symlink_and_force() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -5628,6 +6002,11 @@ mod same_file { // the following tests tries to copy a symlink to the file that symlink points to with // various options #[test] + #[cfg_attr( + wasip2_runner, + ignore = "WASI preview2: rustix::fs::stat doesn't return stable inode identity across path lookups (wasmtime filesystem limitation)" + )] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_symlink_to_file() { for option in ["-d", "-f", "-df", "--rem"] { let scene = TestScenario::new(util_name!()); @@ -5647,6 +6026,11 @@ mod same_file { } #[test] + #[cfg_attr( + wasip2_runner, + ignore = "WASI preview2: rustix::fs::stat doesn't return stable inode identity across path lookups (wasmtime filesystem limitation)" + )] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_symlink_to_file_with_option_backup() { for option in ["-b", "-bf"] { let scene = TestScenario::new(util_name!()); @@ -5665,6 +6049,7 @@ mod same_file { } } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_symlink_to_file_with_option_backup_without_deref() { for option in ["-bd", "-bdf"] { let scene = TestScenario::new(util_name!()); @@ -5686,6 +6071,11 @@ mod same_file { } #[test] + #[cfg_attr( + wasip2_runner, + ignore = "WASI preview2: rustix::fs::stat doesn't return stable inode identity across path lookups (wasmtime filesystem limitation)" + )] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_symlink_to_file_with_options_link() { for option in ["-l", "-dl", "-fl", "-bl", "-bfl"] { let scene = TestScenario::new(util_name!()); @@ -5704,6 +6094,11 @@ mod same_file { } #[test] + #[cfg_attr( + wasip2_runner, + ignore = "WASI preview2: rustix::fs::stat doesn't return stable inode identity across path lookups (wasmtime filesystem limitation)" + )] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_symlink_to_file_with_option_symlink() { for option in ["-s", "-sf"] { let scene = TestScenario::new(util_name!()); @@ -5755,6 +6150,10 @@ mod same_file { } #[test] + #[cfg_attr( + wasi_runner, + ignore = "WASI sandbox: pwd reports the guest's virtual root, not the host's absolute path" + )] fn test_same_file_from_file_to_file_with_options_backup_and_no_deref() { for option in ["-bf", "-bdf"] { let scene = TestScenario::new(util_name!()); @@ -5773,6 +6172,10 @@ mod same_file { } #[test] + #[cfg_attr( + wasi_runner, + ignore = "WASI sandbox: pwd reports the guest's virtual root, not the host's absolute path" + )] fn test_same_file_from_file_to_file_with_options_link() { for option in ["-l", "-dl", "-fl", "-dfl", "-bl", "-bdl"] { let scene = TestScenario::new(util_name!()); @@ -5790,6 +6193,10 @@ mod same_file { } #[test] + #[cfg_attr( + wasi_runner, + ignore = "WASI sandbox: pwd reports the guest's virtual root, not the host's absolute path" + )] fn test_same_file_from_file_to_file_with_options_link_and_backup_and_force() { for option in ["-bfl", "-bdfl"] { let scene = TestScenario::new(util_name!()); @@ -5826,6 +6233,7 @@ mod same_file { // the following tests tries to copy a symlink that points to a file to a symlink // that points to the same file with various options #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_symlink_to_symlink_with_option_no_deref() { for option in ["-d", "-df"] { let scene = TestScenario::new(util_name!()); @@ -5844,6 +6252,11 @@ mod same_file { } #[test] + #[cfg_attr( + wasip2_runner, + ignore = "WASI preview2: rustix::fs::stat doesn't return stable inode identity across path lookups (wasmtime filesystem limitation)" + )] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_symlink_to_symlink_with_option_force() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -5864,6 +6277,7 @@ mod same_file { } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_symlink_to_symlink_with_option_rem() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -5881,6 +6295,7 @@ mod same_file { } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_symlink_to_symlink_with_option_backup() { for option in ["-b", "-bf"] { let scene = TestScenario::new(util_name!()); @@ -5902,6 +6317,7 @@ mod same_file { } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_symlink_to_symlink_with_option_backup_and_no_deref() { for option in ["-bd", "-bdf"] { let scene = TestScenario::new(util_name!()); @@ -5921,6 +6337,7 @@ mod same_file { } } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_symlink_to_symlink_with_option_link() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -5941,6 +6358,7 @@ mod same_file { } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_symlink_to_symlink_with_option_force_link() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -5958,6 +6376,7 @@ mod same_file { } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_symlink_to_symlink_with_option_backup_and_link() { for option in ["-bl", "-bfl"] { let scene = TestScenario::new(util_name!()); @@ -5979,6 +6398,7 @@ mod same_file { } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_symlink_to_symlink_with_option_symlink() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -5999,6 +6419,7 @@ mod same_file { } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_symlink_to_symlink_with_option_symlink_and_force() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -6062,6 +6483,7 @@ mod same_file { } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_file_to_hardlink_with_option_rem() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -6078,6 +6500,7 @@ mod same_file { } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_file_to_hardlink_with_option_backup() { for option in ["-b", "-bd", "-bf", "-bdf"] { let scene = TestScenario::new(util_name!()); @@ -6095,6 +6518,7 @@ mod same_file { } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_file_to_hardlink_with_option_link() { for option in ["-l", "-dl", "-fl", "-dfl", "-bl", "-bdl", "-bfl", "-bdfl"] { let scene = TestScenario::new(util_name!()); @@ -6131,6 +6555,7 @@ mod same_file { // the following tests tries to copy symlink to a hardlink of the same symlink with // various options #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_hard_link_of_symlink_to_symlink() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -6152,6 +6577,7 @@ mod same_file { } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_hard_link_of_symlink_to_symlink_with_option_force() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -6173,6 +6599,7 @@ mod same_file { } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_hard_link_of_symlink_to_symlink_with_option_no_deref() { for option in ["-d", "-df"] { let scene = TestScenario::new(util_name!()); @@ -6195,6 +6622,7 @@ mod same_file { } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_hard_link_of_symlink_to_symlink_with_option_rem() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -6216,6 +6644,7 @@ mod same_file { } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_hard_link_of_symlink_to_symlink_with_option_backup() { for option in ["-b", "-bf"] { let scene = TestScenario::new(util_name!()); @@ -6242,6 +6671,7 @@ mod same_file { } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_hard_link_of_symlink_to_symlink_with_option_backup_and_no_deref() { for option in ["-bd", "-bdf"] { let scene = TestScenario::new(util_name!()); @@ -6267,6 +6697,7 @@ mod same_file { } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_hard_link_of_symlink_to_symlink_with_option_link() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -6288,6 +6719,7 @@ mod same_file { } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_hard_link_of_symlink_to_symlink_with_option_link_and_no_deref() { for option in ["-dl", "-dfl"] { let scene = TestScenario::new(util_name!()); @@ -6310,6 +6742,7 @@ mod same_file { } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_hard_link_of_symlink_to_symlink_with_option_link_and_force() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -6330,6 +6763,7 @@ mod same_file { } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_hard_link_of_symlink_to_symlink_with_option_link_and_backup() { for option in ["-bl", "-bfl"] { let scene = TestScenario::new(util_name!()); @@ -6377,6 +6811,7 @@ mod same_file { } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_hard_link_of_symlink_to_symlink_with_option_symlink() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -6398,6 +6833,7 @@ mod same_file { } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_same_file_from_hard_link_of_symlink_to_symlink_with_option_symlink_and_force() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -6418,6 +6854,7 @@ mod same_file { } #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_hardlink_of_symlink_to_hardlink_of_same_symlink_with_option_no_deref() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -6492,6 +6929,7 @@ mod link_deref { // Dereferencing should fail for dangling symlink. #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_cp_dang_link_as_source_with_link() { for option in ["", "-L", "-H"] { for r in [false, true] { @@ -6516,6 +6954,7 @@ mod link_deref { // Dereferencing should fail for the 'dir_link' without -R. #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_cp_dir_link_as_source_with_link() { for option in ["", "-L", "-H"] { let scene = TestScenario::new(util_name!()); @@ -6535,6 +6974,10 @@ mod link_deref { // cp --link -R 'dir_link' should create a new directory. #[test] + #[cfg_attr( + wasi_runner, + ignore = "WASI: the `same-file` crate has no WASI backend, so same-file detection always errors" + )] fn test_cp_dir_link_as_source_with_link_and_r() { for option in ["", "-L", "-H"] { let scene = TestScenario::new(util_name!()); @@ -6551,6 +6994,7 @@ mod link_deref { //cp --link 'file_link' should create a hard link to the target. #[test] + #[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_cp_file_link_as_source_with_link() { for option in ["", "-L", "-H"] { for r in [false, true] { @@ -6583,6 +7027,10 @@ mod link_deref { #[test] #[cfg(unix)] #[cfg(not(target_os = "openbsd"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_dir_perm_race_with_preserve_mode_and_ownership() { const SRC_DIR: &str = "src"; const DEST_DIR: &str = "dest"; @@ -6638,6 +7086,7 @@ fn test_dir_perm_race_with_preserve_mode_and_ownership() { #[test] // when -d and -a are overridden with --preserve or --no-preserve make sure that it only // overrides attributes not other flags like -r or --no_deref implied in -a and -d. +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_preserve_attrs_overriding_1() { const FILE: &str = "file"; const SYMLINK: &str = "symlink"; @@ -6657,6 +7106,10 @@ fn test_preserve_attrs_overriding_1() { #[test] #[cfg(all(unix, not(target_os = "android")))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_preserve_attrs_overriding_2() { const FILE1: &str = "file1"; const FILE2: &str = "file2"; @@ -6706,6 +7159,10 @@ fn test_preserve_attrs_overriding_2() { /// Test the behavior of preserving permissions when copying through a symlink #[test] #[cfg(unix)] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_symlink_permissions() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -6728,6 +7185,10 @@ fn test_cp_symlink_permissions() { /// Test the behavior of preserving permissions of parents when copying through a symlink #[test] #[cfg(unix)] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_parents_symlink_permissions_file() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -6779,6 +7240,7 @@ fn test_cp_recursive_dest_subdir_symlink_not_followed() { /// destination -- only entries discovered inside the tree are refused. #[test] #[cfg(unix)] +#[cfg_attr(wasi_runner, ignore = "WASI: directory copy with symlinks/metadata not fully supported")] fn test_cp_recursive_target_dir_symlink_still_allowed() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -6796,6 +7258,10 @@ fn test_cp_recursive_target_dir_symlink_still_allowed() { /// a symlink when source is a dir. #[test] #[cfg(unix)] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_parents_symlink_permissions_dir() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -6818,6 +7284,10 @@ fn test_cp_parents_symlink_permissions_dir() { /// Test the behavior of copying a file to a destination with parents using absolute paths. #[cfg(unix)] #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_parents_absolute_path() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -6834,6 +7304,7 @@ fn test_cp_parents_absolute_path() { } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_copy_symlink_overwrite() { let (at, mut ucmd) = at_and_ucmd!(); at.mkdir("a"); @@ -6857,6 +7328,7 @@ fn test_copy_symlink_overwrite() { } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_symlink_mode_overwrite() { let (at, mut ucmd) = at_and_ucmd!(); at.mkdir("a"); @@ -7006,6 +7478,10 @@ fn test_cp_preserve_xattr_readonly_source() { #[test] #[cfg(unix)] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_archive_preserves_directory_permissions() { // Test for issue #8407 let (at, mut ucmd) = at_and_ucmd!(); @@ -7047,6 +7523,10 @@ fn test_cp_archive_preserves_directory_permissions() { #[test] #[cfg(unix)] #[cfg_attr(target_os = "macos", ignore = "Flaky on MacOS, see #8453")] +#[cfg_attr( + all(wasi_runner, not(target_os = "macos")), + ignore = "WASI sandbox: host paths not visible" +)] fn test_cp_from_stdin() { let (at, mut ucmd) = at_and_ucmd!(); let target = "target"; @@ -7115,6 +7595,10 @@ fn test_cp_update_none_interactive_prompt_no() { /// only unix has `/dev/fd/0` #[cfg(unix)] #[cfg_attr(target_os = "macos", ignore = "Flaky on MacOS, see #8453")] +#[cfg_attr( + all(wasi_runner, not(target_os = "macos")), + ignore = "WASI sandbox: host paths not visible" +)] #[test] fn test_cp_from_stream() { let target = "target"; @@ -7142,6 +7626,10 @@ fn test_cp_from_stream() { /// only unix has `/dev/fd/0` #[cfg(unix)] #[cfg_attr(target_os = "macos", ignore = "Flaky on MacOS, see #8453")] +#[cfg_attr( + all(wasi_runner, not(target_os = "macos")), + ignore = "WASI sandbox: host paths not visible" +)] #[test] fn test_cp_from_stream_permission() { let target = "target"; @@ -7565,6 +8053,10 @@ fn test_cp_preserve_context_root() { // to an existing directory, ensuring the directory name is properly // stripped from the descendant path. #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_current_directory_to_existing_directory() { let (at, mut ucmd) = at_and_ucmd!(); @@ -7597,6 +8089,10 @@ fn test_cp_current_directory_to_existing_directory() { // Test copying current directory (.) to a new directory. // This should create the new directory and copy contents. #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_current_directory_to_new_directory() { let (at, mut ucmd) = at_and_ucmd!(); @@ -7625,6 +8121,10 @@ fn test_cp_current_directory_to_new_directory() { // Test copying current directory (.) with verbose output. // This ensures the verbose output shows the correct paths. #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_current_directory_verbose() { let (at, mut ucmd) = at_and_ucmd!(); @@ -7660,6 +8160,10 @@ fn test_cp_current_directory_verbose() { // This ensures attributes are preserved when copying the current directory. #[test] #[cfg(all(not(windows), not(target_os = "freebsd"), not(target_os = "openbsd")))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_current_directory_preserve_attributes() { use filetime::FileTime; use std::os::unix::prelude::MetadataExt; @@ -7746,6 +8250,10 @@ fn test_cp_current_directory_to_itself_disallowed() { // Test copying current directory (.) with symlinks. // This ensures symlinks are handled correctly when copying the current directory. #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_current_directory_with_symlinks() { let (at, mut ucmd) = at_and_ucmd!(); @@ -7775,6 +8283,7 @@ fn test_cp_current_directory_with_symlinks() { #[test] #[cfg(not(windows))] +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_cp_no_dereference_symlink_with_parents() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; @@ -7795,6 +8304,7 @@ fn test_cp_no_dereference_symlink_with_parents() { #[test] #[cfg(unix)] +#[cfg_attr(wasi_runner, ignore = "WASI: directory copy with symlinks/metadata not fully supported")] fn test_cp_recursive_no_dereference_symlink_to_directory() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; @@ -7870,6 +8380,7 @@ fn test_cp_no_preserve_target_directory() { } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: directory copy with symlinks/metadata not fully supported")] fn test_cp_recurse_verbose_output() { let source_dir = "source_dir"; let target_dir = "target_dir"; @@ -7897,6 +8408,7 @@ fn test_cp_recurse_verbose_output() { } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: directory copy with symlinks/metadata not fully supported")] fn test_cp_recurse_verbose_output_with_symlink() { let source_dir = "source_dir"; let target_dir = "target_dir"; @@ -7926,6 +8438,7 @@ fn test_cp_recurse_verbose_output_with_symlink() { } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI: directory copy with symlinks/metadata not fully supported")] fn test_cp_recurse_verbose_output_with_symlink_already_exists() { let source_dir = "source_dir"; let target_dir = "target_dir"; @@ -7959,6 +8472,7 @@ fn test_cp_recurse_verbose_output_with_symlink_already_exists() { #[test] #[cfg(unix)] +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_cp_hlp_flag_ordering() { // GNU cp: "If more than one of -H, -L, and -P is specified, only the final one takes effect" let (at, mut ucmd) = at_and_ucmd!(); @@ -7980,6 +8494,10 @@ fn test_cp_hlp_flag_ordering() { #[test] #[cfg(unix)] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_archive_deref_flag_ordering() { // (flags, expect_symlink): last flag wins; a/d imply -P, H/L dereference for (flags, expect_symlink) in [ @@ -8005,6 +8523,10 @@ fn test_cp_archive_deref_flag_ordering() { /// https://github.com/uutils/coreutils/issues/13207 #[test] #[cfg(unix)] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_archive_deref_preserves_recursive() { for flags in ["-afL", "-aLf", "-aHL", "-adL"] { let (at, mut ucmd) = at_and_ucmd!(); @@ -8022,6 +8544,10 @@ fn test_cp_archive_deref_preserves_recursive() { /// -aL should preserve file permissions (--preserve=all from -a). #[test] #[cfg(unix)] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_archive_deref_preserves_mode() { let (at, mut ucmd) = at_and_ucmd!(); at.mkdir("srcdir"); @@ -8060,6 +8586,10 @@ fn test_cp_no_deref_preserve_with_deref_keeps_hardlinks() { /// while -a preserves them (last-flag-wins for dereference). #[test] #[cfg(unix)] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_archive_deref_symlinks_inside_dir() { use std::os::unix::fs::symlink; let scene = TestScenario::new(util_name!()); @@ -8093,6 +8623,10 @@ fn test_cp_archive_deref_symlinks_inside_dir() { /// -aH: inner symlinks preserved (a wins for recursive), CLI symlinks followed (H wins for CLI). #[test] #[cfg(unix)] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_archive_cli_deref_inner_preserved() { use std::os::unix::fs::symlink; let scene = TestScenario::new(util_name!()); @@ -8119,6 +8653,10 @@ fn test_cp_archive_cli_deref_inner_preserved() { /// Precedence: repeating the same flag should take the last position. #[test] #[cfg(unix)] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_archive_deref_repeated_flag_last_wins() { use std::os::unix::fs::symlink; let scene = TestScenario::new(util_name!()); @@ -8264,6 +8802,10 @@ fn test_cp_xattr_enotsup_handling() { #[test] #[cfg(not(target_os = "windows"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_preserve_directory_permissions_by_default() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; @@ -8430,6 +8972,10 @@ fn test_cp_preserve_context_with_z_fails() { // is exercised by GNU's test suite; documenting here as future coverage. #[test] #[cfg(unix)] +#[cfg_attr( + wasi_runner, + ignore = "WASI: needs investigation (chmod/interactive/device/mode gaps)" +)] fn test_cp_preserve_setuid_when_chown_succeeds() { let (at, mut ucmd) = at_and_ucmd!(); at.touch("src"); @@ -8447,6 +8993,7 @@ fn test_cp_preserve_setuid_when_chown_succeeds() { #[test] #[cfg(all(unix, not(target_os = "macos")))] +#[cfg_attr(wasi_runner, ignore = "WASI: argv/filenames must be valid UTF-8")] fn test_cp_recursive_non_utf8_source() { use std::{ffi::OsStr, os::unix::ffi::OsStrExt}; let (at, mut ucmd) = at_and_ucmd!(); @@ -8494,6 +9041,7 @@ fn test_cp_final_mode_unchanged_after_restrictive_create() { // change drops `O_NOFOLLOW` from the source open under `-P`. #[test] #[cfg(unix)] +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_cp_no_dereference_copies_symlink_as_symlink() { let (at, mut ucmd) = at_and_ucmd!(); at.write("target", "secret target contents"); @@ -8511,6 +9059,7 @@ fn test_cp_no_dereference_copies_symlink_as_symlink() { // O_NOFOLLOW to the dest open broke this and surfaced as ELOOP. #[test] #[cfg(unix)] +#[cfg_attr(wasi_runner, ignore = "WASI: symlinks/hardlinks not supported")] fn test_cp_d_overwrites_existing_symlink_dest() { let (at, mut ucmd) = at_and_ucmd!(); at.touch("f"); @@ -8532,6 +9081,10 @@ fn test_cp_d_overwrites_existing_symlink_dest() { // non-Linux CI do not flag spurious failures. #[test] #[cfg(target_os = "linux")] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sparse/reflink/ACL copy-on-write features not supported" +)] fn test_cp_p_preserves_posix_acls() { use std::process::Command; diff --git a/tests/by-util/test_sort.rs b/tests/by-util/test_sort.rs index cf0244889cd..7ef9c8ea51d 100644 --- a/tests/by-util/test_sort.rs +++ b/tests/by-util/test_sort.rs @@ -36,6 +36,7 @@ fn test_helper(file_name: &str, possible_args: &[&str]) { } #[test] +#[cfg_attr(wasi_runner, ignore)] fn test_buffer_sizes() { #[cfg(target_os = "linux")] let buffer_sizes = ["0", "50K", "50k", "1M", "100M", "0%", "10%"]; @@ -52,6 +53,8 @@ fn test_buffer_sizes() { .stdout_is_fixture("ext_sort.expected"); } + // The wasm guest is always a 32-bit target regardless of the host's + // pointer width, so these overflow there even when the host is 64-bit. #[cfg(not(target_pointer_width = "32"))] { let buffer_sizes = ["1000G", "10T"]; @@ -676,6 +679,7 @@ fn month_sort_input_expected(months: &[String]) -> (String, String) { #[test] #[cfg(unix)] +#[cfg_attr(wasi_runner, ignore = "WASI sandbox: locale database not visible")] fn test_month_sort_french_locale() { let locale = "fr_FR.UTF-8"; if !is_locale_available(locale) { @@ -707,6 +711,7 @@ fn test_month_sort_french_locale() { #[test] #[cfg(unix)] +#[cfg_attr(wasi_runner, ignore = "WASI sandbox: locale database not visible")] fn test_month_sort_hungarian_locale() { let locale = "hu_HU.UTF-8"; if !is_locale_available(locale) { @@ -738,6 +743,7 @@ fn test_month_sort_hungarian_locale() { /// E.g. "av ril" should NOT match "avril" — GNU treats it as unknown. #[test] #[cfg(unix)] +#[cfg_attr(wasi_runner, ignore = "WASI sandbox: locale database not visible")] fn test_month_sort_french_embedded_blanks() { let locale = "fr_FR.UTF-8"; if !is_locale_available(locale) { @@ -790,6 +796,7 @@ fn test_month_sort_french_embedded_blanks() { #[test] #[cfg(unix)] +#[cfg_attr(wasi_runner, ignore = "WASI sandbox: locale database not visible")] fn test_month_sort_japanese_locale() { let locale = "ja_JP.UTF-8"; if !is_locale_available(locale) { @@ -1109,6 +1116,10 @@ fn test_multiple_files() { } #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sort -m spawns real OS threads for multi-file merge, unsupported under wasmtime's default config" +)] fn test_merge_interleaved() { new_ucmd!() .arg("-m") @@ -1120,6 +1131,10 @@ fn test_merge_interleaved() { } #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sort -m spawns real OS threads for multi-file merge, unsupported under wasmtime's default config" +)] fn test_merge_preserves_long_lines() { use std::fmt::Write; @@ -1152,6 +1167,10 @@ fn test_merge_preserves_long_lines() { // receivers while the reader was still sending, and `chunks::read` unwraps that send. #[test] #[cfg(target_os = "linux")] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sort -m spawns real OS threads for multi-file merge, unsupported under wasmtime's default config" +)] fn test_merge_write_error_does_not_panic() { use std::fs::File; @@ -1183,6 +1202,10 @@ fn test_merge_write_error_does_not_panic() { } #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sort -m spawns real OS threads for multi-file merge, unsupported under wasmtime's default config" +)] fn test_merge_unique() { new_ucmd!() .arg("-m") @@ -1198,6 +1221,10 @@ fn test_merge_unique() { } #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sort -m spawns real OS threads for multi-file merge, unsupported under wasmtime's default config" +)] fn test_merge_stable() { new_ucmd!() .arg("-m") @@ -1210,6 +1237,10 @@ fn test_merge_stable() { } #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sort -m spawns real OS threads for multi-file merge, unsupported under wasmtime's default config" +)] fn test_merge_reversed() { new_ucmd!() .arg("-m") @@ -1415,6 +1446,10 @@ fn test_compress() { #[test] #[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sort -m spawns real OS threads for multi-file merge, unsupported under wasmtime's default config" +)] fn test_compress_merge() { new_ucmd!() .args(&[ @@ -1438,6 +1473,10 @@ fn test_compress_merge() { #[test] #[cfg(not(target_os = "android"))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: ext_sort bypasses --compress-program entirely (single-threaded in-memory path)" +)] fn test_compress_fail() { let result = new_ucmd!() .args(&[ @@ -1500,7 +1539,7 @@ fn test_batch_size_too_large() { "--batch-size argument '{large_batch_size}' too large" )); - #[cfg(target_os = "linux")] + #[cfg(all(target_os = "linux", not(wasi_runner)))] new_ucmd!() .arg(format!("--batch-size={large_batch_size}")) .fails_with_code(2) @@ -1508,6 +1547,10 @@ fn test_batch_size_too_large() { } #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sort -m spawns real OS threads for multi-file merge, unsupported under wasmtime's default config" +)] fn test_merge_batch_size() { new_ucmd!() .arg("--batch-size=2") @@ -1527,6 +1570,10 @@ fn test_merge_batch_size() { // TODO(#7542): Re-enable on Android once we figure out why setting limit is broken. // #[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(target_os = "linux")] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sort -m spawns real OS threads for multi-file merge, unsupported under wasmtime's default config" +)] fn test_merge_batch_size_with_limit() { use rlimit::Resource; // Currently need... @@ -1646,6 +1693,10 @@ fn test_verifies_files_after_keys() { #[test] #[cfg(unix)] +#[cfg_attr( + wasi_runner, + ignore = "WASI sandbox: host paths (/dev/random) not visible" +)] fn test_verifies_input_files() { new_ucmd!() .args(&["/dev/random", "nonexistent_file"]) @@ -1663,6 +1714,10 @@ fn test_separator_null() { } #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sort -m spawns real OS threads, unsupported under wasmtime's default config" +)] fn test_output_is_input() { let input = "a\nb\nc\n"; let (at, mut ucmd) = at_and_ucmd!(); @@ -1677,6 +1732,10 @@ fn test_output_is_input() { #[test] #[cfg(unix)] +#[cfg_attr( + wasi_runner, + ignore = "WASI sandbox: host paths (/dev/null) not visible" +)] fn test_output_device() { new_ucmd!() .args(&["-o", "/dev/null"]) @@ -1685,6 +1744,10 @@ fn test_output_device() { } #[test] +#[cfg_attr( + wasi_runner, + ignore = "WASI: sort -m spawns real OS threads for multi-file merge, unsupported under wasmtime's default config" +)] fn test_merge_empty_input() { new_ucmd!() .args(&["-m", "empty.txt"]) @@ -1710,6 +1773,7 @@ fn test_wrong_args_exit_code() { #[test] #[cfg(unix)] +#[cfg_attr(wasi_runner, ignore = "WASI: no signal support (SIGINT)")] fn test_tmp_files_deleted_on_sigint() { use rand::{RngExt as _, SeedableRng, rngs::SmallRng}; use rustix::process::{Pid, Signal, kill_process}; @@ -1795,6 +1859,7 @@ fn test_args_check_conflict() { #[cfg(target_os = "linux")] #[test] +#[cfg_attr(wasi_runner, ignore = "WASI P2: /dev/full filesystem not available")] fn test_failed_write_is_reported() { new_ucmd!() .pipe_in("hello") @@ -1897,6 +1962,10 @@ fn test_files0_from_empty() { #[test] #[cfg(unix)] +#[cfg_attr( + wasi_runner, + ignore = "WASI preview2: error message text for this OS error differs from native Unix" +)] fn test_files0_from_non_utf8_name() { new_ucmd!() .args(&["--files0-from", "-"]) @@ -1907,6 +1976,10 @@ fn test_files0_from_non_utf8_name() { #[test] #[cfg(unix)] +#[cfg_attr( + wasi_runner, + ignore = "WASI: error message text for this OS error differs from native Unix" +)] fn test_files0_read_error() { new_ucmd!() .args(&["--files0-from", "."]) @@ -1917,6 +1990,7 @@ fn test_files0_read_error() { #[cfg(unix)] #[test] // Test for GNU tests/sort/sort-files0-from.pl "empty-non-regular" +#[cfg_attr(wasi_runner, ignore = "WASI sandbox: host paths not visible")] fn test_files0_from_empty_non_regular() { new_ucmd!() .args(&["--files0-from", "/dev/null"]) @@ -2003,6 +2077,10 @@ fn test_files0_from_2a() { #[test] // Test for GNU tests/sort/sort-files0-from.pl "non-utf8" #[cfg(all(unix, not(target_os = "macos")))] +#[cfg_attr( + wasi_runner, + ignore = "WASI: preopened directories reject non-UTF-8 filenames" +)] fn test_files0_from_non_utf8() { use std::os::unix::ffi::OsStringExt; let (at, mut ucmd) = at_and_ucmd!(); @@ -2989,6 +3067,7 @@ fn test_locale_collation_utf8() { } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI sandbox: locale database not visible")] fn test_locale_interleaved_en_us_utf8() { // Test case for issue: locale-based collation support // In en_US.UTF-8, lowercase and uppercase letters should interleave @@ -3061,6 +3140,7 @@ fn test_locale_with_ignore_case_flag() { } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI sandbox: locale database not visible")] fn test_locale_complex_utf8_sorting() { // More complex test with mixed case and special characters // In en_US.UTF-8, should respect locale collation rules @@ -3085,6 +3165,7 @@ fn test_locale_posix_sort_debug_message() { } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI sandbox: locale database not visible")] fn test_locale_utf8_sort_debug_message() { new_ucmd!() .env("LC_ALL", "en_US.UTF-8") @@ -3105,7 +3186,7 @@ fn test_failed_to_set_locale_debug_message() { result.stderr_contains("text ordering performed using simple byte comparison"); - #[cfg(all(target_os = "linux", target_env = "gnu"))] + #[cfg(all(target_os = "linux", target_env = "gnu", not(wasi_runner)))] result.stderr_contains("failed to set locale"); } @@ -3127,6 +3208,7 @@ e f 5436 down data path1 path2 path3 path4 path5\n"; } #[test] +#[cfg_attr(wasi_runner, ignore = "WASI sandbox: locale database not visible")] fn test_consistent_sorting_with_i18n_collate() { // Regression test for issue #11980 // Lexicographic fallback sorting for equal sorting keys for 01 and 0_1