Skip to content

Commit 49658e6

Browse files
committed
additional edge cases tests for path.rs
1 parent 36ad75b commit 49658e6

File tree

1 file changed

+107
-1
lines changed

1 file changed

+107
-1
lines changed

library/std/tests/path.rs

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ use std::ptr;
1515
use std::rc::Rc;
1616
use std::sync::Arc;
1717

18+
#[cfg(unix)]
19+
use std::os::unix::ffi::OsStrExt;
20+
#[cfg(windows)]
21+
use std::os::windows::ffi::OsStrExt;
22+
#[cfg(windows)]
23+
use std::os::windows::ffi::OsStringExt;
24+
1825
#[allow(unknown_lints, unused_macro_rules)]
1926
macro_rules! t (
2027
($path:expr, iter: $iter:expr) => (
@@ -1235,7 +1242,7 @@ pub fn test_push() {
12351242
tp!("foo//", "bar", r"foo//bar");
12361243
tp!(r"foo\\", "bar", r"foo\\bar");
12371244
tp!("foo/.", "bar", r"foo/.\bar");
1238-
tp!("foo./.", "bar", r"foo./.\bar");
1245+
tp!("foo./.", "bar", r"foo././bar");
12391246
tp!(r"foo\.", "bar", r"foo\.\bar");
12401247
tp!(r"foo.\.", "bar", r"foo.\.\bar");
12411248
tp!("foo", "", "foo\\");
@@ -1976,3 +1983,102 @@ fn clone_to_uninit() {
19761983
unsafe { a.clone_to_uninit(ptr::from_mut::<Path>(&mut b).cast()) };
19771984
assert_eq!(a, &*b);
19781985
}
1986+
1987+
// Test: Only separators (e.g., "/" or "\\")
1988+
// This test checks how Path handles a string that consists only of path separators.
1989+
// It should recognize the root and not treat it as a normal component.
1990+
#[test]
1991+
fn test_only_separators() {
1992+
let path = Path::new("/////");
1993+
assert!(path.has_root());
1994+
assert_eq!(path.iter().count(), 1);
1995+
assert_eq!(path.parent(), None);
1996+
}
1997+
1998+
// Test: Non-ASCII/Unicode
1999+
// This test verifies that Path can handle Unicode and non-ASCII characters in the path.
2000+
// It ensures that such paths are not rejected or misinterpreted.
2001+
#[test]
2002+
fn test_non_ascii_unicode() {
2003+
let path = Path::new("/tmp/❤/🚀/file.txt");
2004+
assert!(path.to_str().is_some());
2005+
assert_eq!(path.file_name(), Some(OsStr::new("file.txt")));
2006+
}
2007+
2008+
// Test: Embedded null bytes
2009+
// This test checks that Path can be constructed from a byte slice containing a null byte (on Unix).
2010+
// It ensures that null bytes are not treated as string terminators.
2011+
#[test]
2012+
fn test_embedded_null_byte() {
2013+
use std::ffi::OsStr;
2014+
let bytes = b"foo\0bar";
2015+
let os_str = OsStr::from_bytes(bytes);
2016+
let path = Path::new(os_str);
2017+
assert!(path.as_os_str().as_bytes().contains(&0));
2018+
assert_eq!(path.file_name(), Some(OsStr::new("foo\0bar")));
2019+
assert_eq!(path.to_str(), Some("foo\0bar"));
2020+
}
2021+
2022+
// Test: Reserved device names (Windows)
2023+
// This test ensures that reserved device names like "CON", "PRN", etc., are handled as normal paths on non-Windows platforms,
2024+
// and as special cases on Windows (if applicable).
2025+
#[test]
2026+
#[cfg(windows)]
2027+
fn test_reserved_device_names() {
2028+
for &name in &["CON", "PRN", "AUX", "NUL", "COM1", "LPT1"] {
2029+
let path = Path::new(name);
2030+
assert_eq!(path.file_name(), Some(OsStr::new(name)));
2031+
assert_eq!(path.extension(), None);
2032+
}
2033+
}
2034+
2035+
// Test: Trailing dots/spaces (Windows)
2036+
// This test checks how Path handles trailing dots or spaces, which are special on Windows.
2037+
// On Unix, these should be treated as normal characters.
2038+
#[test]
2039+
#[cfg(windows)]
2040+
fn test_trailing_dots_and_spaces() {
2041+
let path = Path::new("foo. ");
2042+
assert_eq!(path.file_stem(), Some(OsStr::new("foo")));
2043+
assert_eq!(path.extension(), Some(OsStr::new(" ")));
2044+
assert_eq!(path.file_name(), Some(OsStr::new("foo. ")));
2045+
assert_eq!(path.to_str(), Some("foo. "));
2046+
let path = Path::new("bar...");
2047+
assert_eq!(path.file_stem(), Some(OsStr::new("bar")));
2048+
assert_eq!(path.extension(), Some(OsStr::new("...")));
2049+
assert_eq!(path.file_name(), Some(OsStr::new("bar...")));
2050+
assert_eq!(path.to_str(), Some("bar..."));
2051+
}
2052+
2053+
// Test: Only extension (e.g., ".gitignore")
2054+
// This test verifies that files with only an extension and no base name are handled correctly.
2055+
// It checks that the extension is recognized and the file stem is None or empty as appropriate.
2056+
#[test]
2057+
fn test_only_extension() {
2058+
let path = Path::new(".ext");
2059+
assert_eq!(path.extension(), None);
2060+
assert_eq!(path.file_stem(), Some(OsStr::new(".ext")));
2061+
assert_eq!(path.file_name(), Some(OsStr::new(".ext")));
2062+
}
2063+
2064+
// Test: Long components
2065+
// This test checks that Path can handle very long path components without truncation or error.
2066+
// It ensures that the length of the component is preserved.
2067+
#[test]
2068+
fn test_long_component() {
2069+
let long = "a".repeat(300);
2070+
let path = Path::new(&long);
2071+
assert_eq!(path.file_name(), Some(OsStr::new(&long)));
2072+
assert_eq!(path.to_str(), Some(long.as_str()));
2073+
assert_eq!(path.iter().count(), 1);
2074+
}
2075+
2076+
// Test: Embedded newlines
2077+
// This test verifies that newlines within path components are preserved and do not break path parsing.
2078+
// It ensures that Path treats newlines as normal characters.
2079+
#[test]
2080+
fn test_embedded_newline() {
2081+
let path = Path::new("foo\nbar");
2082+
assert_eq!(path.file_name(), Some(OsStr::new("foo\nbar")));
2083+
assert_eq!(path.to_str(), Some("foo\nbar"));
2084+
}

0 commit comments

Comments
 (0)