From 450fa2d09d63b18bf121b5edf453dee265ba5a00 Mon Sep 17 00:00:00 2001 From: Shawn <118158941+kevinWangSheng@users.noreply.github.com> Date: Mon, 19 Jan 2026 20:51:47 +0800 Subject: [PATCH] fs: add tests for when `fs::hard_link` fails (#7863) --- tokio/tests/fs_link.rs | 54 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/tokio/tests/fs_link.rs b/tokio/tests/fs_link.rs index 4e6742a57..ef143678b 100644 --- a/tokio/tests/fs_link.rs +++ b/tokio/tests/fs_link.rs @@ -60,3 +60,57 @@ async fn test_symlink() { let symlink_meta = fs::symlink_metadata(dst.clone()).await.unwrap(); assert!(symlink_meta.file_type().is_symlink()); } + +#[tokio::test] +#[cfg_attr(miri, ignore)] // No `linkat` in miri. +async fn test_hard_link_error_source_not_found() { + let dir = tempdir().unwrap(); + let src = dir.path().join("nonexistent.txt"); + let dst = dir.path().join("dst.txt"); + + let err = fs::hard_link(&src, &dst).await.unwrap_err(); + assert_eq!(err.kind(), std::io::ErrorKind::NotFound); +} + +#[tokio::test] +#[cfg_attr(miri, ignore)] // No `linkat` in miri. +async fn test_hard_link_error_destination_already_exists() { + let dir = tempdir().unwrap(); + let src = dir.path().join("src.txt"); + let dst = dir.path().join("dst.txt"); + + // Create source file + std::fs::write(&src, b"source content").unwrap(); + + // Create destination file + std::fs::write(&dst, b"destination content").unwrap(); + + // Attempt to create hard link when destination already exists + let err = fs::hard_link(&src, &dst).await.unwrap_err(); + assert_eq!(err.kind(), std::io::ErrorKind::AlreadyExists); +} + +#[tokio::test] +#[cfg_attr(miri, ignore)] // No `linkat` in miri. +async fn test_hard_link_error_source_is_directory() { + let dir = tempdir().unwrap(); + let src_dir = dir.path().join("src_directory"); + let dst = dir.path().join("dst.txt"); + + // Create source directory + fs::create_dir(&src_dir).await.unwrap(); + + // Attempt to create hard link from a directory + // On most systems, hard linking directories is not allowed + let err = fs::hard_link(&src_dir, &dst).await.unwrap_err(); + + // Different platforms return different error kinds + #[cfg(unix)] + assert!( + err.kind() == std::io::ErrorKind::PermissionDenied + || err.kind() == std::io::ErrorKind::Other + ); + + #[cfg(windows)] + assert_eq!(err.kind(), std::io::ErrorKind::PermissionDenied); +}