3 use crate::collections::hash_map::DefaultHasher;
4 use crate::collections::{BTreeSet, HashSet};
5 use crate::hash::Hasher;
8 use core::hint::black_box;
10 #[allow(unknown_lints, unused_macro_rules)]
12 ($path:expr, iter: $iter:expr) => (
14 let path = Path::new($path);
17 let comps = path.iter()
18 .map(|p| p.to_string_lossy().into_owned())
19 .collect::<Vec<String>>();
20 let exp: &[&str] = &$iter;
21 let exps = exp.iter().map(|s| s.to_string()).collect::<Vec<String>>();
22 assert!(comps == exps, "iter: Expected {:?}, found {:?}",
26 let comps = Path::new($path).iter().rev()
27 .map(|p| p.to_string_lossy().into_owned())
28 .collect::<Vec<String>>();
29 let exps = exps.into_iter().rev().collect::<Vec<String>>();
30 assert!(comps == exps, "iter().rev(): Expected {:?}, found {:?}",
35 ($path:expr, has_root: $has_root:expr, is_absolute: $is_absolute:expr) => (
37 let path = Path::new($path);
39 let act_root = path.has_root();
40 assert!(act_root == $has_root, "has_root: Expected {:?}, found {:?}",
43 let act_abs = path.is_absolute();
44 assert!(act_abs == $is_absolute, "is_absolute: Expected {:?}, found {:?}",
45 $is_absolute, act_abs);
49 ($path:expr, parent: $parent:expr, file_name: $file:expr) => (
51 let path = Path::new($path);
53 let parent = path.parent().map(|p| p.to_str().unwrap());
54 let exp_parent: Option<&str> = $parent;
55 assert!(parent == exp_parent, "parent: Expected {:?}, found {:?}",
58 let file = path.file_name().map(|p| p.to_str().unwrap());
59 let exp_file: Option<&str> = $file;
60 assert!(file == exp_file, "file_name: Expected {:?}, found {:?}",
65 ($path:expr, file_stem: $file_stem:expr, extension: $extension:expr) => (
67 let path = Path::new($path);
69 let stem = path.file_stem().map(|p| p.to_str().unwrap());
70 let exp_stem: Option<&str> = $file_stem;
71 assert!(stem == exp_stem, "file_stem: Expected {:?}, found {:?}",
74 let ext = path.extension().map(|p| p.to_str().unwrap());
75 let exp_ext: Option<&str> = $extension;
76 assert!(ext == exp_ext, "extension: Expected {:?}, found {:?}",
81 ($path:expr, file_prefix: $file_prefix:expr, extension: $extension:expr) => (
83 let path = Path::new($path);
85 let prefix = path.file_prefix().map(|p| p.to_str().unwrap());
86 let exp_prefix: Option<&str> = $file_prefix;
87 assert!(prefix == exp_prefix, "file_prefix: Expected {:?}, found {:?}",
90 let ext = path.extension().map(|p| p.to_str().unwrap());
91 let exp_ext: Option<&str> = $extension;
92 assert!(ext == exp_ext, "extension: Expected {:?}, found {:?}",
97 ($path:expr, iter: $iter:expr,
98 has_root: $has_root:expr, is_absolute: $is_absolute:expr,
99 parent: $parent:expr, file_name: $file:expr,
100 file_stem: $file_stem:expr, extension: $extension:expr,
101 file_prefix: $file_prefix:expr) => (
103 t!($path, iter: $iter);
104 t!($path, has_root: $has_root, is_absolute: $is_absolute);
105 t!($path, parent: $parent, file_name: $file);
106 t!($path, file_stem: $file_stem, extension: $extension);
107 t!($path, file_prefix: $file_prefix, extension: $extension);
114 use crate::borrow::Cow;
116 let static_path = Path::new("/home/foo");
117 let static_cow_path: Cow<'static, Path> = static_path.into();
118 let pathbuf = PathBuf::from("/home/foo");
121 let path: &Path = &pathbuf;
122 let borrowed_cow_path: Cow<'_, Path> = path.into();
124 assert_eq!(static_cow_path, borrowed_cow_path);
127 let owned_cow_path: Cow<'static, Path> = pathbuf.into();
129 assert_eq!(static_cow_path, owned_cow_path);
134 pub fn test_decompositions_unix() {
151 file_name: Some("foo"),
152 file_stem: Some("foo"),
154 file_prefix: Some("foo")
173 file_name: Some("foo"),
174 file_stem: Some("foo"),
176 file_prefix: Some("foo")
184 file_name: Some("foo"),
185 file_stem: Some("foo"),
187 file_prefix: Some("foo")
195 file_name: Some("foo"),
196 file_stem: Some("foo"),
198 file_prefix: Some("foo")
202 iter: ["foo", "bar"],
206 file_name: Some("bar"),
207 file_stem: Some("bar"),
209 file_prefix: Some("bar")
213 iter: ["/", "foo", "bar"],
216 parent: Some("/foo"),
217 file_name: Some("bar"),
218 file_stem: Some("bar"),
220 file_prefix: Some("bar")
228 file_name: Some("foo"),
229 file_stem: Some("foo"),
231 file_prefix: Some("foo")
235 iter: ["/", "foo", "bar"],
238 parent: Some("///foo"),
239 file_name: Some("bar"),
240 file_stem: Some("bar"),
242 file_prefix: Some("bar")
283 file_name: Some("foo"),
284 file_stem: Some("foo"),
286 file_prefix: Some("foo")
305 file_name: Some("foo"),
306 file_stem: Some("foo"),
308 file_prefix: Some("foo")
312 iter: ["foo", "bar"],
316 file_name: Some("bar"),
317 file_stem: Some("bar"),
319 file_prefix: Some("bar")
334 iter: ["foo", "..", "bar"],
337 parent: Some("foo/.."),
338 file_name: Some("bar"),
339 file_stem: Some("bar"),
341 file_prefix: Some("bar")
349 file_name: Some("a"),
350 file_stem: Some("a"),
352 file_prefix: Some("a")
382 file_name: Some("b"),
383 file_stem: Some("b"),
385 file_prefix: Some("b")
393 file_name: Some("b"),
394 file_stem: Some("b"),
396 file_prefix: Some("b")
404 file_name: Some("b"),
405 file_stem: Some("b"),
407 file_prefix: Some("b")
411 iter: ["a", "b", "c"],
415 file_name: Some("c"),
416 file_stem: Some("c"),
418 file_prefix: Some("c")
426 file_name: Some(".foo"),
427 file_stem: Some(".foo"),
429 file_prefix: Some(".foo")
437 file_name: Some(".foo"),
438 file_stem: Some(".foo"),
440 file_prefix: Some(".foo")
443 t!("a/.rustfmt.toml",
444 iter: ["a", ".rustfmt.toml"],
448 file_name: Some(".rustfmt.toml"),
449 file_stem: Some(".rustfmt"),
450 extension: Some("toml"),
451 file_prefix: Some(".rustfmt")
455 iter: ["a", ".x.y.z"],
459 file_name: Some(".x.y.z"),
460 file_stem: Some(".x.y"),
461 extension: Some("z"),
462 file_prefix: Some(".x")
468 pub fn test_decompositions_windows() {
485 file_name: Some("foo"),
486 file_stem: Some("foo"),
488 file_prefix: Some("foo")
551 file_name: Some("foo"),
552 file_stem: Some("foo"),
554 file_prefix: Some("foo")
562 file_name: Some("foo"),
563 file_stem: Some("foo"),
565 file_prefix: Some("foo")
573 file_name: Some("foo"),
574 file_stem: Some("foo"),
576 file_prefix: Some("foo")
580 iter: ["foo", "bar"],
584 file_name: Some("bar"),
585 file_stem: Some("bar"),
587 file_prefix: Some("bar")
591 iter: ["\\", "foo", "bar"],
594 parent: Some("/foo"),
595 file_name: Some("bar"),
596 file_stem: Some("bar"),
598 file_prefix: Some("bar")
606 file_name: Some("foo"),
607 file_stem: Some("foo"),
609 file_prefix: Some("foo")
613 iter: ["\\", "foo", "bar"],
616 parent: Some("///foo"),
617 file_name: Some("bar"),
618 file_stem: Some("bar"),
620 file_prefix: Some("bar")
661 file_name: Some("foo"),
662 file_stem: Some("foo"),
664 file_prefix: Some("foo")
683 file_name: Some("foo"),
684 file_stem: Some("foo"),
686 file_prefix: Some("foo")
690 iter: ["foo", "bar"],
694 file_name: Some("bar"),
695 file_stem: Some("bar"),
697 file_prefix: Some("bar")
712 iter: ["foo", "..", "bar"],
715 parent: Some("foo/.."),
716 file_name: Some("bar"),
717 file_stem: Some("bar"),
719 file_prefix: Some("bar")
727 file_name: Some("a"),
728 file_stem: Some("a"),
730 file_prefix: Some("a")
760 file_name: Some("b"),
761 file_stem: Some("b"),
763 file_prefix: Some("b")
771 file_name: Some("b"),
772 file_stem: Some("b"),
774 file_prefix: Some("b")
782 file_name: Some("b"),
783 file_stem: Some("b"),
785 file_prefix: Some("b")
789 iter: ["a", "b", "c"],
793 file_name: Some("c"),
794 file_stem: Some("c"),
796 file_prefix: Some("c")
800 iter: ["a", "b", "c"],
803 parent: Some("a\\b"),
804 file_name: Some("c"),
805 file_stem: Some("c"),
807 file_prefix: Some("c")
815 file_name: Some("a"),
816 file_stem: Some("a"),
818 file_prefix: Some("a")
822 iter: ["c:", "\\", "foo.txt"],
825 parent: Some("c:\\"),
826 file_name: Some("foo.txt"),
827 file_stem: Some("foo"),
828 extension: Some("txt"),
829 file_prefix: Some("foo")
832 t!("\\\\server\\share\\foo.txt",
833 iter: ["\\\\server\\share", "\\", "foo.txt"],
836 parent: Some("\\\\server\\share\\"),
837 file_name: Some("foo.txt"),
838 file_stem: Some("foo"),
839 extension: Some("txt"),
840 file_prefix: Some("foo")
843 t!("\\\\server\\share",
844 iter: ["\\\\server\\share", "\\"],
855 iter: ["\\", "server"],
859 file_name: Some("server"),
860 file_stem: Some("server"),
862 file_prefix: Some("server")
865 t!("\\\\?\\bar\\foo.txt",
866 iter: ["\\\\?\\bar", "\\", "foo.txt"],
869 parent: Some("\\\\?\\bar\\"),
870 file_name: Some("foo.txt"),
871 file_stem: Some("foo"),
872 extension: Some("txt"),
873 file_prefix: Some("foo")
877 iter: ["\\\\?\\bar"],
898 t!("\\\\?\\UNC\\server\\share\\foo.txt",
899 iter: ["\\\\?\\UNC\\server\\share", "\\", "foo.txt"],
902 parent: Some("\\\\?\\UNC\\server\\share\\"),
903 file_name: Some("foo.txt"),
904 file_stem: Some("foo"),
905 extension: Some("txt"),
906 file_prefix: Some("foo")
909 t!("\\\\?\\UNC\\server",
910 iter: ["\\\\?\\UNC\\server"],
921 iter: ["\\\\?\\UNC\\"],
931 t!("\\\\?\\C:\\foo.txt",
932 iter: ["\\\\?\\C:", "\\", "foo.txt"],
935 parent: Some("\\\\?\\C:\\"),
936 file_name: Some("foo.txt"),
937 file_stem: Some("foo"),
938 extension: Some("txt"),
939 file_prefix: Some("foo")
943 iter: ["\\\\?\\C:", "\\"],
965 iter: ["\\\\?\\foo/bar"],
975 t!("\\\\?\\C:/foo/bar",
976 iter: ["\\\\?\\C:", "\\", "foo/bar"],
979 parent: Some("\\\\?\\C:/"),
980 file_name: Some("foo/bar"),
981 file_stem: Some("foo/bar"),
983 file_prefix: Some("foo/bar")
986 t!("\\\\.\\foo\\bar",
987 iter: ["\\\\.\\foo", "\\", "bar"],
990 parent: Some("\\\\.\\foo\\"),
991 file_name: Some("bar"),
992 file_stem: Some("bar"),
994 file_prefix: Some("bar")
998 iter: ["\\\\.\\foo", "\\"],
1008 t!("\\\\.\\foo/bar",
1009 iter: ["\\\\.\\foo", "\\", "bar"],
1012 parent: Some("\\\\.\\foo/"),
1013 file_name: Some("bar"),
1014 file_stem: Some("bar"),
1016 file_prefix: Some("bar")
1019 t!("\\\\.\\foo\\bar/baz",
1020 iter: ["\\\\.\\foo", "\\", "bar", "baz"],
1023 parent: Some("\\\\.\\foo\\bar"),
1024 file_name: Some("baz"),
1025 file_stem: Some("baz"),
1027 file_prefix: Some("baz")
1031 iter: ["\\\\.\\", "\\"],
1042 iter: ["\\\\?\\a", "\\", "b"],
1045 parent: Some("\\\\?\\a\\"),
1046 file_name: Some("b"),
1047 file_stem: Some("b"),
1049 file_prefix: Some("b")
1052 t!("\\\\?\\C:\\foo.txt.zip",
1053 iter: ["\\\\?\\C:", "\\", "foo.txt.zip"],
1056 parent: Some("\\\\?\\C:\\"),
1057 file_name: Some("foo.txt.zip"),
1058 file_stem: Some("foo.txt"),
1059 extension: Some("zip"),
1060 file_prefix: Some("foo")
1063 t!("\\\\?\\C:\\.foo.txt.zip",
1064 iter: ["\\\\?\\C:", "\\", ".foo.txt.zip"],
1067 parent: Some("\\\\?\\C:\\"),
1068 file_name: Some(".foo.txt.zip"),
1069 file_stem: Some(".foo.txt"),
1070 extension: Some("zip"),
1071 file_prefix: Some(".foo")
1074 t!("\\\\?\\C:\\.foo",
1075 iter: ["\\\\?\\C:", "\\", ".foo"],
1078 parent: Some("\\\\?\\C:\\"),
1079 file_name: Some(".foo"),
1080 file_stem: Some(".foo"),
1082 file_prefix: Some(".foo")
1086 iter: ["a", ".x.y.z"],
1090 file_name: Some(".x.y.z"),
1091 file_stem: Some(".x.y"),
1092 extension: Some("z"),
1093 file_prefix: Some(".x")
1098 pub fn test_stem_ext() {
1100 file_stem: Some("foo"),
1105 file_stem: Some("foo"),
1110 file_stem: Some(".foo"),
1115 file_stem: Some("foo"),
1116 extension: Some("txt")
1120 file_stem: Some("foo.bar"),
1121 extension: Some("txt")
1125 file_stem: Some("foo.bar"),
1129 t!(".", file_stem: None, extension: None);
1131 t!("..", file_stem: None, extension: None);
1133 t!(".x.y.z", file_stem: Some(".x.y"), extension: Some("z"));
1135 t!("..x.y.z", file_stem: Some("..x.y"), extension: Some("z"));
1137 t!("", file_stem: None, extension: None);
1141 pub fn test_prefix_ext() {
1143 file_prefix: Some("foo"),
1148 file_prefix: Some("foo"),
1153 file_prefix: Some(".foo"),
1158 file_prefix: Some("foo"),
1159 extension: Some("txt")
1163 file_prefix: Some("foo"),
1164 extension: Some("txt")
1168 file_prefix: Some("foo"),
1172 t!(".", file_prefix: None, extension: None);
1174 t!("..", file_prefix: None, extension: None);
1176 t!(".x.y.z", file_prefix: Some(".x"), extension: Some("z"));
1178 t!("..x.y.z", file_prefix: Some("."), extension: Some("z"));
1180 t!("", file_prefix: None, extension: None);
1184 pub fn test_push() {
1186 ($path:expr, $push:expr, $expected:expr) => ( {
1187 let mut actual = PathBuf::from($path);
1189 assert!(actual.to_str() == Some($expected),
1190 "pushing {:?} onto {:?}: Expected {:?}, got {:?}",
1191 $push, $path, $expected, actual.to_str().unwrap());
1195 if cfg!(unix) || cfg!(all(target_env = "sgx", target_vendor = "fortanix")) {
1196 tp!("", "foo", "foo");
1197 tp!("foo", "bar", "foo/bar");
1198 tp!("foo/", "bar", "foo/bar");
1199 tp!("foo//", "bar", "foo//bar");
1200 tp!("foo/.", "bar", "foo/./bar");
1201 tp!("foo./.", "bar", "foo././bar");
1202 tp!("foo", "", "foo/");
1203 tp!("foo", ".", "foo/.");
1204 tp!("foo", "..", "foo/..");
1205 tp!("foo", "/", "/");
1206 tp!("/foo/bar", "/", "/");
1207 tp!("/foo/bar", "/baz", "/baz");
1208 tp!("/foo/bar", "./baz", "/foo/bar/./baz");
1210 tp!("", "foo", "foo");
1211 tp!("foo", "bar", r"foo\bar");
1212 tp!("foo/", "bar", r"foo/bar");
1213 tp!(r"foo\", "bar", r"foo\bar");
1214 tp!("foo//", "bar", r"foo//bar");
1215 tp!(r"foo\\", "bar", r"foo\\bar");
1216 tp!("foo/.", "bar", r"foo/.\bar");
1217 tp!("foo./.", "bar", r"foo./.\bar");
1218 tp!(r"foo\.", "bar", r"foo\.\bar");
1219 tp!(r"foo.\.", "bar", r"foo.\.\bar");
1220 tp!("foo", "", "foo\\");
1221 tp!("foo", ".", r"foo\.");
1222 tp!("foo", "..", r"foo\..");
1223 tp!("foo", "/", "/");
1224 tp!("foo", r"\", r"\");
1225 tp!("/foo/bar", "/", "/");
1226 tp!(r"\foo\bar", r"\", r"\");
1227 tp!("/foo/bar", "/baz", "/baz");
1228 tp!("/foo/bar", r"\baz", r"\baz");
1229 tp!("/foo/bar", "./baz", r"/foo/bar\./baz");
1230 tp!("/foo/bar", r".\baz", r"/foo/bar\.\baz");
1232 tp!("c:\\", "windows", "c:\\windows");
1233 tp!("c:", "windows", "c:windows");
1235 tp!("a\\b\\c", "d", "a\\b\\c\\d");
1236 tp!("\\a\\b\\c", "d", "\\a\\b\\c\\d");
1237 tp!("a\\b", "c\\d", "a\\b\\c\\d");
1238 tp!("a\\b", "\\c\\d", "\\c\\d");
1239 tp!("a\\b", ".", "a\\b\\.");
1240 tp!("a\\b", "..\\c", "a\\b\\..\\c");
1241 tp!("a\\b", "C:a.txt", "C:a.txt");
1242 tp!("a\\b", "C:\\a.txt", "C:\\a.txt");
1243 tp!("C:\\a", "C:\\b.txt", "C:\\b.txt");
1244 tp!("C:\\a\\b\\c", "C:d", "C:d");
1245 tp!("C:a\\b\\c", "C:d", "C:d");
1246 tp!("C:", r"a\b\c", r"C:a\b\c");
1247 tp!("C:", r"..\a", r"C:..\a");
1248 tp!("\\\\server\\share\\foo", "bar", "\\\\server\\share\\foo\\bar");
1249 tp!("\\\\server\\share\\foo", "C:baz", "C:baz");
1250 tp!("\\\\?\\C:\\a\\b", "C:c\\d", "C:c\\d");
1251 tp!("\\\\?\\C:a\\b", "C:c\\d", "C:c\\d");
1252 tp!("\\\\?\\C:\\a\\b", "C:\\c\\d", "C:\\c\\d");
1253 tp!("\\\\?\\foo\\bar", "baz", "\\\\?\\foo\\bar\\baz");
1254 tp!("\\\\?\\UNC\\server\\share\\foo", "bar", "\\\\?\\UNC\\server\\share\\foo\\bar");
1255 tp!("\\\\?\\UNC\\server\\share", "C:\\a", "C:\\a");
1256 tp!("\\\\?\\UNC\\server\\share", "C:a", "C:a");
1258 // Note: modified from old path API
1259 tp!("\\\\?\\UNC\\server", "foo", "\\\\?\\UNC\\server\\foo");
1261 tp!("C:\\a", "\\\\?\\UNC\\server\\share", "\\\\?\\UNC\\server\\share");
1262 tp!("\\\\.\\foo\\bar", "baz", "\\\\.\\foo\\bar\\baz");
1263 tp!("\\\\.\\foo\\bar", "C:a", "C:a");
1264 // again, not sure about the following, but I'm assuming \\.\ should be verbatim
1265 tp!("\\\\.\\foo", "..\\bar", "\\\\.\\foo\\..\\bar");
1267 tp!("\\\\?\\C:", "foo", "\\\\?\\C:\\foo"); // this is a weird one
1269 tp!(r"\\?\C:\bar", "../foo", r"\\?\C:\foo");
1270 tp!(r"\\?\C:\bar", "../../foo", r"\\?\C:\foo");
1271 tp!(r"\\?\C:\", "../foo", r"\\?\C:\foo");
1272 tp!(r"\\?\C:", r"D:\foo/./", r"D:\foo/./");
1273 tp!(r"\\?\C:", r"\\?\D:\foo\.\", r"\\?\D:\foo\.\");
1274 tp!(r"\\?\A:\x\y", "/foo", r"\\?\A:\foo");
1275 tp!(r"\\?\A:", r"..\foo\.", r"\\?\A:\foo");
1276 tp!(r"\\?\A:\x\y", r".\foo\.", r"\\?\A:\x\y\foo");
1277 tp!(r"\\?\A:\x\y", r"", r"\\?\A:\x\y\");
1284 ($path:expr, $expected:expr, $output:expr) => ( {
1285 let mut actual = PathBuf::from($path);
1286 let output = actual.pop();
1287 assert!(actual.to_str() == Some($expected) && output == $output,
1288 "popping from {:?}: Expected {:?}/{:?}, got {:?}/{:?}",
1289 $path, $expected, $output,
1290 actual.to_str().unwrap(), output);
1295 tp!("/", "/", false);
1296 tp!("foo", "", true);
1298 tp!("/foo", "/", true);
1299 tp!("/foo/bar", "/foo", true);
1300 tp!("foo/bar", "foo", true);
1301 tp!("foo/.", "", true);
1302 tp!("foo//bar", "foo", true);
1305 tp!("a\\b\\c", "a\\b", true);
1306 tp!("\\a", "\\", true);
1307 tp!("\\", "\\", false);
1309 tp!("C:\\a\\b", "C:\\a", true);
1310 tp!("C:\\a", "C:\\", true);
1311 tp!("C:\\", "C:\\", false);
1312 tp!("C:a\\b", "C:a", true);
1313 tp!("C:a", "C:", true);
1314 tp!("C:", "C:", false);
1315 tp!("\\\\server\\share\\a\\b", "\\\\server\\share\\a", true);
1316 tp!("\\\\server\\share\\a", "\\\\server\\share\\", true);
1317 tp!("\\\\server\\share", "\\\\server\\share", false);
1318 tp!("\\\\?\\a\\b\\c", "\\\\?\\a\\b", true);
1319 tp!("\\\\?\\a\\b", "\\\\?\\a\\", true);
1320 tp!("\\\\?\\a", "\\\\?\\a", false);
1321 tp!("\\\\?\\C:\\a\\b", "\\\\?\\C:\\a", true);
1322 tp!("\\\\?\\C:\\a", "\\\\?\\C:\\", true);
1323 tp!("\\\\?\\C:\\", "\\\\?\\C:\\", false);
1324 tp!("\\\\?\\UNC\\server\\share\\a\\b", "\\\\?\\UNC\\server\\share\\a", true);
1325 tp!("\\\\?\\UNC\\server\\share\\a", "\\\\?\\UNC\\server\\share\\", true);
1326 tp!("\\\\?\\UNC\\server\\share", "\\\\?\\UNC\\server\\share", false);
1327 tp!("\\\\.\\a\\b\\c", "\\\\.\\a\\b", true);
1328 tp!("\\\\.\\a\\b", "\\\\.\\a\\", true);
1329 tp!("\\\\.\\a", "\\\\.\\a", false);
1331 tp!("\\\\?\\a\\b\\", "\\\\?\\a\\", true);
1336 pub fn test_set_file_name() {
1338 ($path:expr, $file:expr, $expected:expr) => ( {
1339 let mut p = PathBuf::from($path);
1340 p.set_file_name($file);
1341 assert!(p.to_str() == Some($expected),
1342 "setting file name of {:?} to {:?}: Expected {:?}, got {:?}",
1343 $path, $file, $expected,
1344 p.to_str().unwrap());
1348 tfn!("foo", "foo", "foo");
1349 tfn!("foo", "bar", "bar");
1350 tfn!("foo", "", "");
1351 tfn!("", "foo", "foo");
1352 if cfg!(unix) || cfg!(all(target_env = "sgx", target_vendor = "fortanix")) {
1353 tfn!(".", "foo", "./foo");
1354 tfn!("foo/", "bar", "bar");
1355 tfn!("foo/.", "bar", "bar");
1356 tfn!("..", "foo", "../foo");
1357 tfn!("foo/..", "bar", "foo/../bar");
1358 tfn!("/", "foo", "/foo");
1360 tfn!(".", "foo", r".\foo");
1361 tfn!(r"foo\", "bar", r"bar");
1362 tfn!(r"foo\.", "bar", r"bar");
1363 tfn!("..", "foo", r"..\foo");
1364 tfn!(r"foo\..", "bar", r"foo\..\bar");
1365 tfn!(r"\", "foo", r"\foo");
1370 pub fn test_set_extension() {
1372 ($path:expr, $ext:expr, $expected:expr, $output:expr) => ( {
1373 let mut p = PathBuf::from($path);
1374 let output = p.set_extension($ext);
1375 assert!(p.to_str() == Some($expected) && output == $output,
1376 "setting extension of {:?} to {:?}: Expected {:?}/{:?}, got {:?}/{:?}",
1377 $path, $ext, $expected, $output,
1378 p.to_str().unwrap(), output);
1382 tfe!("foo", "txt", "foo.txt", true);
1383 tfe!("foo.bar", "txt", "foo.txt", true);
1384 tfe!("foo.bar.baz", "txt", "foo.bar.txt", true);
1385 tfe!(".test", "txt", ".test.txt", true);
1386 tfe!("foo.txt", "", "foo", true);
1387 tfe!("foo", "", "foo", true);
1388 tfe!("", "foo", "", false);
1389 tfe!(".", "foo", ".", false);
1390 tfe!("foo/", "bar", "foo.bar", true);
1391 tfe!("foo/.", "bar", "foo.bar", true);
1392 tfe!("..", "foo", "..", false);
1393 tfe!("foo/..", "bar", "foo/..", false);
1394 tfe!("/", "foo", "/", false);
1398 fn test_eq_receivers() {
1399 use crate::borrow::Cow;
1401 let borrowed: &Path = Path::new("foo/bar");
1402 let mut owned: PathBuf = PathBuf::new();
1405 let borrowed_cow: Cow<'_, Path> = borrowed.into();
1406 let owned_cow: Cow<'_, Path> = owned.clone().into();
1409 ($($current:expr),+) => {
1411 assert_eq!($current, borrowed);
1412 assert_eq!($current, owned);
1413 assert_eq!($current, borrowed_cow);
1414 assert_eq!($current, owned_cow);
1419 t!(borrowed, owned, borrowed_cow, owned_cow);
1423 pub fn test_compare() {
1424 use crate::collections::hash_map::DefaultHasher;
1425 use crate::hash::{Hash, Hasher};
1427 fn hash<T: Hash>(t: T) -> u64 {
1428 let mut s = DefaultHasher::new();
1434 ($path1:expr, $path2:expr, eq: $eq:expr,
1435 starts_with: $starts_with:expr, ends_with: $ends_with:expr,
1436 relative_from: $relative_from:expr) => ({
1437 let path1 = Path::new($path1);
1438 let path2 = Path::new($path2);
1440 let eq = path1 == path2;
1441 assert!(eq == $eq, "{:?} == {:?}, expected {:?}, got {:?}",
1442 $path1, $path2, $eq, eq);
1443 assert!($eq == (hash(path1) == hash(path2)),
1444 "{:?} == {:?}, expected {:?}, got {} and {}",
1445 $path1, $path2, $eq, hash(path1), hash(path2));
1447 let starts_with = path1.starts_with(path2);
1448 assert!(starts_with == $starts_with,
1449 "{:?}.starts_with({:?}), expected {:?}, got {:?}", $path1, $path2,
1450 $starts_with, starts_with);
1452 let ends_with = path1.ends_with(path2);
1453 assert!(ends_with == $ends_with,
1454 "{:?}.ends_with({:?}), expected {:?}, got {:?}", $path1, $path2,
1455 $ends_with, ends_with);
1457 let relative_from = path1.strip_prefix(path2)
1458 .map(|p| p.to_str().unwrap())
1460 let exp: Option<&str> = $relative_from;
1461 assert!(relative_from == exp,
1462 "{:?}.strip_prefix({:?}), expected {:?}, got {:?}",
1463 $path1, $path2, exp, relative_from);
1471 relative_from: Some("")
1478 relative_from: Some("foo")
1492 relative_from: Some("")
1499 relative_from: Some("")
1506 relative_from: Some("")
1509 tc!("foo/./bar", "foo/bar",
1513 relative_from: Some("")
1516 tc!("foo/bar", "foo",
1520 relative_from: Some("bar")
1523 tc!("foo/bar/baz", "foo/bar",
1527 relative_from: Some("baz")
1530 tc!("foo/bar", "foo/bar/baz",
1537 tc!("./foo/bar/", ".",
1541 relative_from: Some("foo/bar")
1545 tc!(r"C:\src\rust\cargo-test\test\Cargo.toml",
1546 r"c:\src\rust\cargo-test\test",
1550 relative_from: Some("Cargo.toml")
1553 tc!(r"c:\foo", r"C:\foo",
1557 relative_from: Some("")
1560 tc!(r"C:\foo\.\bar.txt", r"C:\foo\bar.txt",
1564 relative_from: Some("")
1567 tc!(r"C:\foo\.", r"C:\foo",
1571 relative_from: Some("")
1574 tc!(r"\\?\C:\foo\.\bar.txt", r"\\?\C:\foo\bar.txt",
1584 fn test_components_debug() {
1585 let path = Path::new("/tmp");
1587 let mut components = path.components();
1589 let expected = "Components([RootDir, Normal(\"tmp\")])";
1590 let actual = format!("{components:?}");
1591 assert_eq!(expected, actual);
1593 let _ = components.next().unwrap();
1594 let expected = "Components([Normal(\"tmp\")])";
1595 let actual = format!("{components:?}");
1596 assert_eq!(expected, actual);
1598 let _ = components.next().unwrap();
1599 let expected = "Components([])";
1600 let actual = format!("{components:?}");
1601 assert_eq!(expected, actual);
1606 fn test_iter_debug() {
1607 let path = Path::new("/tmp");
1609 let mut iter = path.iter();
1611 let expected = "Iter([\"/\", \"tmp\"])";
1612 let actual = format!("{iter:?}");
1613 assert_eq!(expected, actual);
1615 let _ = iter.next().unwrap();
1616 let expected = "Iter([\"tmp\"])";
1617 let actual = format!("{iter:?}");
1618 assert_eq!(expected, actual);
1620 let _ = iter.next().unwrap();
1621 let expected = "Iter([])";
1622 let actual = format!("{iter:?}");
1623 assert_eq!(expected, actual);
1628 let orig: &str = "some/sort/of/path";
1629 let path = Path::new(orig);
1630 let boxed: Box<Path> = Box::from(path);
1631 let path_buf = path.to_owned().into_boxed_path().into_path_buf();
1632 assert_eq!(path, &*boxed);
1633 assert_eq!(&*boxed, &*path_buf);
1634 assert_eq!(&*path_buf, path);
1638 fn test_clone_into() {
1639 let mut path_buf = PathBuf::from("supercalifragilisticexpialidocious");
1640 let path = Path::new("short");
1641 path.clone_into(&mut path_buf);
1642 assert_eq!(path, path_buf);
1643 assert!(path_buf.into_os_string().capacity() >= 15);
1647 fn display_format_flags() {
1648 assert_eq!(format!("a{:#<5}b", Path::new("").display()), "a#####b");
1649 assert_eq!(format!("a{:#<5}b", Path::new("a").display()), "aa####b");
1654 let orig = "hello/world";
1655 let path = Path::new(orig);
1656 let rc: Rc<Path> = Rc::from(path);
1657 let arc: Arc<Path> = Arc::from(path);
1659 assert_eq!(&*rc, path);
1660 assert_eq!(&*arc, path);
1662 let rc2: Rc<Path> = Rc::from(path.to_owned());
1663 let arc2: Arc<Path> = Arc::from(path.to_owned());
1665 assert_eq!(&*rc2, path);
1666 assert_eq!(&*arc2, path);
1672 ($ord:ident, $left:expr, $right:expr) => ( {
1673 use core::cmp::Ordering;
1675 let left = Path::new($left);
1676 let right = Path::new($right);
1677 assert_eq!(left.cmp(&right), Ordering::$ord);
1678 if (core::cmp::Ordering::$ord == Ordering::Equal) {
1679 assert_eq!(left, right);
1681 let mut hasher = DefaultHasher::new();
1682 left.hash(&mut hasher);
1683 let left_hash = hasher.finish();
1684 hasher = DefaultHasher::new();
1685 right.hash(&mut hasher);
1686 let right_hash = hasher.finish();
1688 assert_eq!(left_hash, right_hash, "hashes for {:?} and {:?} must match", left, right);
1690 assert_ne!(left, right);
1695 ord!(Less, "1", "2");
1696 ord!(Less, "/foo/bar", "/foo./bar");
1697 ord!(Less, "foo/bar", "foo/bar.");
1698 ord!(Equal, "foo/./bar", "foo/bar/");
1699 ord!(Equal, "foo/bar", "foo/bar/");
1700 ord!(Equal, "foo/bar", "foo/bar/.");
1701 ord!(Equal, "foo/bar", "foo/bar//");
1706 fn test_unix_absolute() {
1707 use crate::path::absolute;
1709 assert!(absolute("").is_err());
1711 let relative = "a/b";
1712 let mut expected = crate::env::current_dir().unwrap();
1713 expected.push(relative);
1714 assert_eq!(absolute(relative).unwrap().as_os_str(), expected.as_os_str());
1716 // Test how components are collected.
1717 assert_eq!(absolute("/a/b/c").unwrap().as_os_str(), Path::new("/a/b/c").as_os_str());
1718 assert_eq!(absolute("/a//b/c").unwrap().as_os_str(), Path::new("/a/b/c").as_os_str());
1719 assert_eq!(absolute("//a/b/c").unwrap().as_os_str(), Path::new("//a/b/c").as_os_str());
1720 assert_eq!(absolute("///a/b/c").unwrap().as_os_str(), Path::new("/a/b/c").as_os_str());
1721 assert_eq!(absolute("/a/b/c/").unwrap().as_os_str(), Path::new("/a/b/c/").as_os_str());
1723 absolute("/a/./b/../c/.././..").unwrap().as_os_str(),
1724 Path::new("/a/b/../c/../..").as_os_str()
1727 // Test leading `.` and `..` components
1728 let curdir = crate::env::current_dir().unwrap();
1729 assert_eq!(absolute("./a").unwrap().as_os_str(), curdir.join("a").as_os_str());
1730 assert_eq!(absolute("../a").unwrap().as_os_str(), curdir.join("../a").as_os_str()); // return /pwd/../a
1735 fn test_windows_absolute() {
1736 use crate::path::absolute;
1737 // An empty path is an error.
1738 assert!(absolute("").is_err());
1740 let relative = r"a\b";
1741 let mut expected = crate::env::current_dir().unwrap();
1742 expected.push(relative);
1743 assert_eq!(absolute(relative).unwrap().as_os_str(), expected.as_os_str());
1745 macro_rules! unchanged(
1747 assert_eq!(absolute($path).unwrap().as_os_str(), Path::new($path).as_os_str());
1751 unchanged!(r"C:\path\to\file");
1752 unchanged!(r"C:\path\to\file\");
1753 unchanged!(r"\\server\share\to\file");
1754 unchanged!(r"\\server.\share.\to\file");
1755 unchanged!(r"\\.\PIPE\name");
1756 unchanged!(r"\\.\C:\path\to\COM1");
1757 unchanged!(r"\\?\C:\path\to\file");
1758 unchanged!(r"\\?\UNC\server\share\to\file");
1759 unchanged!(r"\\?\PIPE\name");
1760 // Verbatim paths are always unchanged, no matter what.
1761 unchanged!(r"\\?\path.\to/file..");
1764 absolute(r"C:\path..\to.\file.").unwrap().as_os_str(),
1765 Path::new(r"C:\path..\to\file").as_os_str()
1767 assert_eq!(absolute(r"COM1").unwrap().as_os_str(), Path::new(r"\\.\COM1").as_os_str());
1771 #[cfg_attr(miri, ignore)] // Miri isn't fast...
1772 fn bench_path_cmp_fast_path_buf_sort(b: &mut test::Bencher) {
1773 let prefix = "my/home";
1774 let mut paths: Vec<_> =
1775 (0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect();
1780 black_box(paths.as_mut_slice()).sort_unstable();
1785 #[cfg_attr(miri, ignore)] // Miri isn't fast...
1786 fn bench_path_cmp_fast_path_long(b: &mut test::Bencher) {
1787 let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/";
1789 (0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect();
1791 let mut set = BTreeSet::new();
1793 paths.iter().for_each(|p| {
1794 set.insert(p.as_path());
1798 set.remove(paths[500].as_path());
1799 set.insert(paths[500].as_path());
1804 #[cfg_attr(miri, ignore)] // Miri isn't fast...
1805 fn bench_path_cmp_fast_path_short(b: &mut test::Bencher) {
1806 let prefix = "my/home";
1808 (0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect();
1810 let mut set = BTreeSet::new();
1812 paths.iter().for_each(|p| {
1813 set.insert(p.as_path());
1817 set.remove(paths[500].as_path());
1818 set.insert(paths[500].as_path());
1823 #[cfg_attr(miri, ignore)] // Miri isn't fast...
1824 fn bench_path_hashset(b: &mut test::Bencher) {
1825 let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/";
1827 (0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect();
1829 let mut set = HashSet::new();
1831 paths.iter().for_each(|p| {
1832 set.insert(p.as_path());
1836 set.remove(paths[500].as_path());
1837 set.insert(black_box(paths[500].as_path()))
1842 #[cfg_attr(miri, ignore)] // Miri isn't fast...
1843 fn bench_path_hashset_miss(b: &mut test::Bencher) {
1844 let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/";
1846 (0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect();
1848 let mut set = HashSet::new();
1850 paths.iter().for_each(|p| {
1851 set.insert(p.as_path());
1854 let probe = PathBuf::from(prefix).join("other");
1856 b.iter(|| set.remove(black_box(probe.as_path())));
1860 fn bench_hash_path_short(b: &mut test::Bencher) {
1861 let mut hasher = DefaultHasher::new();
1862 let path = Path::new("explorer.exe");
1864 b.iter(|| black_box(path).hash(&mut hasher));
1866 black_box(hasher.finish());
1870 fn bench_hash_path_long(b: &mut test::Bencher) {
1871 let mut hasher = DefaultHasher::new();
1873 Path::new("/aaaaa/aaaaaa/./../aaaaaaaa/bbbbbbbbbbbbb/ccccccccccc/ddddddddd/eeeeeee.fff");
1875 b.iter(|| black_box(path).hash(&mut hasher));
1877 black_box(hasher.finish());