1 use std::error::Error;
2 use std::path::{Path, PathBuf};
3 use walkdir::WalkDir;
4
5 #[test]
trybuild()6 fn trybuild() {
7 let directory = PathBuf::from("tests/try_build");
8
9 let mut _renamer = None;
10
11 let compile_fail_dir = directory.join("compile_fail");
12
13 // Sometimes error messages change on beta/nightly - allow alternate errors on those.
14 _renamer = Some(Renamer::rename(compile_fail_dir.clone()).unwrap());
15
16 let fail = trybuild::TestCases::new();
17 fail.compile_fail(compile_fail_dir.join("*.rs"));
18 add_feature_dirs(&compile_fail_dir, &fail, ExpectedResult::Fail);
19
20 let pass = trybuild::TestCases::new();
21 let pass_dir = directory.join("pass");
22 pass.pass(pass_dir.join("*.rs"));
23 add_feature_dirs(&pass_dir, &pass, ExpectedResult::Pass);
24 }
25
26 enum ExpectedResult {
27 Pass,
28 Fail,
29 }
30
add_feature_dirs( parent_dir: &Path, test_cases: &trybuild::TestCases, expected_result: ExpectedResult, )31 fn add_feature_dirs(
32 parent_dir: &Path,
33 test_cases: &trybuild::TestCases,
34 expected_result: ExpectedResult,
35 ) {
36 let features_dir = parent_dir.join("features");
37 let feature_specific_dir = if cfg!(feature = "complex-expressions") {
38 features_dir.join("complex-expressions")
39 } else {
40 features_dir.join("!complex-expressions")
41 };
42 let tests = feature_specific_dir.join("*.rs");
43 match expected_result {
44 ExpectedResult::Pass => test_cases.pass(tests),
45 ExpectedResult::Fail => test_cases.compile_fail(tests),
46 }
47 }
48
49 struct Renamer(Vec<PathBuf>);
50
51 impl Renamer {
52 const STDERR_EXTENSION: &'static str = "stderr";
53
54 #[rustversion::all(beta)]
55 const VERSION_SPECIFIC_EXTENSION: &'static str = "stderr_beta";
56
57 #[rustversion::all(nightly)]
58 const VERSION_SPECIFIC_EXTENSION: &'static str = "stderr_nightly";
59
60 #[rustversion::all(not(beta), not(nightly))]
61 const VERSION_SPECIFIC_EXTENSION: &'static str = "stderr_doesnotexist";
62
63 const NON_VERSION_SPECIFIC_BACKUP_EXTENSION: &'static str =
64 "stderr_non_version_specific_backup";
65
rename(dir: PathBuf) -> anyhow::Result<Self>66 fn rename(dir: PathBuf) -> anyhow::Result<Self> {
67 let nightly_paths = WalkDir::new(dir)
68 .max_depth(1)
69 .into_iter()
70 .filter_map(|dir_entry| {
71 let dir_entry = match dir_entry {
72 Ok(dir_entry) => dir_entry,
73 Err(err) => return Some(Err(err)),
74 };
75 let path = dir_entry.path();
76 if let Some(file_name) = path.file_name() {
77 if Path::new(file_name).extension()
78 == Some(Renamer::VERSION_SPECIFIC_EXTENSION.as_ref())
79 {
80 return Some(Ok(path.to_path_buf()));
81 }
82 }
83 None
84 })
85 .collect::<Result<Vec<_>, _>>()?;
86 // Create early so that if we end up returning an error this gets dropped and undoes any
87 // already-done renames.
88 let renamer = Renamer(nightly_paths);
89
90 for nightly_path in &renamer.0 {
91 std::fs::rename(
92 nightly_path.with_extension(Renamer::STDERR_EXTENSION),
93 nightly_path.with_extension(Renamer::NON_VERSION_SPECIFIC_BACKUP_EXTENSION),
94 )?;
95 std::fs::rename(
96 nightly_path.with_extension(Renamer::VERSION_SPECIFIC_EXTENSION),
97 nightly_path.with_extension(Renamer::STDERR_EXTENSION),
98 )?;
99 }
100 Ok(renamer)
101 }
102 }
103
104 impl Drop for Renamer {
drop(&mut self)105 fn drop(&mut self) {
106 for path in &self.0 {
107 ignore_error(std::fs::rename(
108 path.with_extension(Renamer::STDERR_EXTENSION),
109 path.with_extension(Renamer::VERSION_SPECIFIC_EXTENSION),
110 ));
111 ignore_error(std::fs::rename(
112 path.with_extension(Renamer::NON_VERSION_SPECIFIC_BACKUP_EXTENSION),
113 path.with_extension(Renamer::STDERR_EXTENSION),
114 ));
115 }
116 }
117 }
118
ignore_error<T, E: Error>(result: Result<T, E>)119 fn ignore_error<T, E: Error>(result: Result<T, E>) {
120 if let Err(err) = result {
121 eprintln!("Ignoring error: {}", err);
122 }
123 }
124