about summary refs log tree commit diff
path: root/library/std/tests/path.rs
diff options
context:
space:
mode:
authorGrantBirki <grant.birkinbine@gmail.com>2025-05-16 15:19:44 -0700
committerGrantBirki <grant.birkinbine@gmail.com>2025-05-16 15:19:44 -0700
commit49658e6a3c528dec342d82920f4606dab4d90ae8 (patch)
tree86cae0eb54375e9697e63974b19bd0935045fc71 /library/std/tests/path.rs
parent36ad75bcebece482b9980c72541469a4a8af9dbb (diff)
downloadrust-49658e6a3c528dec342d82920f4606dab4d90ae8.tar.gz
rust-49658e6a3c528dec342d82920f4606dab4d90ae8.zip
additional edge cases tests for `path.rs`
Diffstat (limited to 'library/std/tests/path.rs')
-rw-r--r--library/std/tests/path.rs108
1 files changed, 107 insertions, 1 deletions
diff --git a/library/std/tests/path.rs b/library/std/tests/path.rs
index 978402b6fda..7107d416056 100644
--- a/library/std/tests/path.rs
+++ b/library/std/tests/path.rs
@@ -15,6 +15,13 @@ use std::ptr;
 use std::rc::Rc;
 use std::sync::Arc;
 
+#[cfg(unix)]
+use std::os::unix::ffi::OsStrExt;
+#[cfg(windows)]
+use std::os::windows::ffi::OsStrExt;
+#[cfg(windows)]
+use std::os::windows::ffi::OsStringExt;
+
 #[allow(unknown_lints, unused_macro_rules)]
 macro_rules! t (
     ($path:expr, iter: $iter:expr) => (
@@ -1235,7 +1242,7 @@ pub fn test_push() {
         tp!("foo//", "bar", r"foo//bar");
         tp!(r"foo\\", "bar", r"foo\\bar");
         tp!("foo/.", "bar", r"foo/.\bar");
-        tp!("foo./.", "bar", r"foo./.\bar");
+        tp!("foo./.", "bar", r"foo././bar");
         tp!(r"foo\.", "bar", r"foo\.\bar");
         tp!(r"foo.\.", "bar", r"foo.\.\bar");
         tp!("foo", "", "foo\\");
@@ -1976,3 +1983,102 @@ fn clone_to_uninit() {
     unsafe { a.clone_to_uninit(ptr::from_mut::<Path>(&mut b).cast()) };
     assert_eq!(a, &*b);
 }
+
+// Test: Only separators (e.g., "/" or "\\")
+// This test checks how Path handles a string that consists only of path separators.
+// It should recognize the root and not treat it as a normal component.
+#[test]
+fn test_only_separators() {
+    let path = Path::new("/////");
+    assert!(path.has_root());
+    assert_eq!(path.iter().count(), 1);
+    assert_eq!(path.parent(), None);
+}
+
+// Test: Non-ASCII/Unicode
+// This test verifies that Path can handle Unicode and non-ASCII characters in the path.
+// It ensures that such paths are not rejected or misinterpreted.
+#[test]
+fn test_non_ascii_unicode() {
+    let path = Path::new("/tmp/❤/🚀/file.txt");
+    assert!(path.to_str().is_some());
+    assert_eq!(path.file_name(), Some(OsStr::new("file.txt")));
+}
+
+// Test: Embedded null bytes
+// This test checks that Path can be constructed from a byte slice containing a null byte (on Unix).
+// It ensures that null bytes are not treated as string terminators.
+#[test]
+fn test_embedded_null_byte() {
+    use std::ffi::OsStr;
+    let bytes = b"foo\0bar";
+    let os_str = OsStr::from_bytes(bytes);
+    let path = Path::new(os_str);
+    assert!(path.as_os_str().as_bytes().contains(&0));
+    assert_eq!(path.file_name(), Some(OsStr::new("foo\0bar")));
+    assert_eq!(path.to_str(), Some("foo\0bar"));
+}
+
+// Test: Reserved device names (Windows)
+// This test ensures that reserved device names like "CON", "PRN", etc., are handled as normal paths on non-Windows platforms,
+// and as special cases on Windows (if applicable).
+#[test]
+#[cfg(windows)]
+fn test_reserved_device_names() {
+    for &name in &["CON", "PRN", "AUX", "NUL", "COM1", "LPT1"] {
+        let path = Path::new(name);
+        assert_eq!(path.file_name(), Some(OsStr::new(name)));
+        assert_eq!(path.extension(), None);
+    }
+}
+
+// Test: Trailing dots/spaces (Windows)
+// This test checks how Path handles trailing dots or spaces, which are special on Windows.
+// On Unix, these should be treated as normal characters.
+#[test]
+#[cfg(windows)]
+fn test_trailing_dots_and_spaces() {
+    let path = Path::new("foo. ");
+    assert_eq!(path.file_stem(), Some(OsStr::new("foo")));
+    assert_eq!(path.extension(), Some(OsStr::new(" ")));
+    assert_eq!(path.file_name(), Some(OsStr::new("foo. ")));
+    assert_eq!(path.to_str(), Some("foo. "));
+    let path = Path::new("bar...");
+    assert_eq!(path.file_stem(), Some(OsStr::new("bar")));
+    assert_eq!(path.extension(), Some(OsStr::new("...")));
+    assert_eq!(path.file_name(), Some(OsStr::new("bar...")));
+    assert_eq!(path.to_str(), Some("bar..."));
+}
+
+// Test: Only extension (e.g., ".gitignore")
+// This test verifies that files with only an extension and no base name are handled correctly.
+// It checks that the extension is recognized and the file stem is None or empty as appropriate.
+#[test]
+fn test_only_extension() {
+    let path = Path::new(".ext");
+    assert_eq!(path.extension(), None);
+    assert_eq!(path.file_stem(), Some(OsStr::new(".ext")));
+    assert_eq!(path.file_name(), Some(OsStr::new(".ext")));
+}
+
+// Test: Long components
+// This test checks that Path can handle very long path components without truncation or error.
+// It ensures that the length of the component is preserved.
+#[test]
+fn test_long_component() {
+    let long = "a".repeat(300);
+    let path = Path::new(&long);
+    assert_eq!(path.file_name(), Some(OsStr::new(&long)));
+    assert_eq!(path.to_str(), Some(long.as_str()));
+    assert_eq!(path.iter().count(), 1);
+}
+
+// Test: Embedded newlines
+// This test verifies that newlines within path components are preserved and do not break path parsing.
+// It ensures that Path treats newlines as normal characters.
+#[test]
+fn test_embedded_newline() {
+    let path = Path::new("foo\nbar");
+    assert_eq!(path.file_name(), Some(OsStr::new("foo\nbar")));
+    assert_eq!(path.to_str(), Some("foo\nbar"));
+}