1 #![allow(clippy::manual_assert)]
2 
3 mod progress;
4 
5 use self::progress::Progress;
6 use anyhow::Result;
7 use flate2::read::GzDecoder;
8 use std::fs;
9 use std::path::Path;
10 use tar::Archive;
11 use walkdir::DirEntry;
12 
13 const REVISION: &str = "ac2d9fc509e36d1b32513744adf58c34bcc4f43c";
14 
15 #[rustfmt::skip]
16 static EXCLUDE: &[&str] = &[
17     // TODO: impl ~const T {}
18     // https://github.com/dtolnay/syn/issues/1051
19     "src/test/ui/rfc-2632-const-trait-impl/syntax.rs",
20 
21     // Compile-fail expr parameter in const generic position: f::<1 + 2>()
22     "src/test/ui/const-generics/early/closing-args-token.rs",
23     "src/test/ui/const-generics/early/const-expression-parameter.rs",
24 
25     // Deprecated anonymous parameter syntax in traits
26     "src/test/ui/issues/issue-13105.rs",
27     "src/test/ui/issues/issue-13775.rs",
28     "src/test/ui/issues/issue-34074.rs",
29     "src/test/ui/proc-macro/trait-fn-args-2015.rs",
30     "src/tools/rustfmt/tests/source/trait.rs",
31     "src/tools/rustfmt/tests/target/trait.rs",
32 
33     // Excessive nesting
34     "src/test/ui/issues/issue-74564-if-expr-stack-overflow.rs",
35 
36     // Testing rustfmt on invalid syntax
37     "src/tools/rustfmt/tests/coverage/target/comments.rs",
38     "src/tools/rustfmt/tests/parser/issue-4126/invalid.rs",
39     "src/tools/rustfmt/tests/parser/issue_4418.rs",
40     "src/tools/rustfmt/tests/parser/unclosed-delims/issue_4466.rs",
41     "src/tools/rustfmt/tests/source/configs/disable_all_formatting/true.rs",
42     "src/tools/rustfmt/tests/source/configs/spaces_around_ranges/false.rs",
43     "src/tools/rustfmt/tests/source/configs/spaces_around_ranges/true.rs",
44     "src/tools/rustfmt/tests/source/type.rs",
45     "src/tools/rustfmt/tests/target/configs/spaces_around_ranges/false.rs",
46     "src/tools/rustfmt/tests/target/configs/spaces_around_ranges/true.rs",
47     "src/tools/rustfmt/tests/target/type.rs",
48 
49     // Not actually test cases
50     "src/test/rustdoc-ui/test-compile-fail2.rs",
51     "src/test/rustdoc-ui/test-compile-fail3.rs",
52     "src/test/ui/include-single-expr-helper.rs",
53     "src/test/ui/include-single-expr-helper-1.rs",
54     "src/test/ui/json-bom-plus-crlf-multifile-aux.rs",
55     "src/test/ui/lint/expansion-time-include.rs",
56     "src/test/ui/macros/auxiliary/macro-comma-support.rs",
57     "src/test/ui/macros/auxiliary/macro-include-items-expr.rs",
58     "src/test/ui/parser/auxiliary/issue-21146-inc.rs",
59 ];
60 
base_dir_filter(entry: &DirEntry) -> bool61 pub fn base_dir_filter(entry: &DirEntry) -> bool {
62     let path = entry.path();
63     if path.is_dir() {
64         return true; // otherwise walkdir does not visit the files
65     }
66     if path.extension().map_or(true, |e| e != "rs") {
67         return false;
68     }
69 
70     let mut path_string = path.to_string_lossy();
71     if cfg!(windows) {
72         path_string = path_string.replace('\\', "/").into();
73     }
74     let path = if let Some(path) = path_string.strip_prefix("tests/rust/") {
75         path
76     } else {
77         panic!("unexpected path in Rust dist: {}", path_string);
78     };
79 
80     if path.starts_with("src/test/compile-fail") || path.starts_with("src/test/rustfix") {
81         return false;
82     }
83 
84     if path.starts_with("src/test/ui") {
85         let stderr_path = entry.path().with_extension("stderr");
86         if stderr_path.exists() {
87             // Expected to fail in some way
88             return false;
89         }
90     }
91 
92     !EXCLUDE.contains(&path)
93 }
94 
95 #[allow(dead_code)]
edition(path: &Path) -> &'static str96 pub fn edition(path: &Path) -> &'static str {
97     if path.ends_with("dyn-2015-no-warnings-without-lints.rs") {
98         "2015"
99     } else {
100         "2018"
101     }
102 }
103 
clone_rust()104 pub fn clone_rust() {
105     let needs_clone = match fs::read_to_string("tests/rust/COMMIT") {
106         Err(_) => true,
107         Ok(contents) => contents.trim() != REVISION,
108     };
109     if needs_clone {
110         download_and_unpack().unwrap();
111     }
112     let mut missing = String::new();
113     let test_src = Path::new("tests/rust");
114     for exclude in EXCLUDE {
115         if !test_src.join(exclude).exists() {
116             missing += "\ntests/rust/";
117             missing += exclude;
118         }
119     }
120     if !missing.is_empty() {
121         panic!("excluded test file does not exist:{}\n", missing);
122     }
123 }
124 
download_and_unpack() -> Result<()>125 fn download_and_unpack() -> Result<()> {
126     let url = format!(
127         "https://github.com/rust-lang/rust/archive/{}.tar.gz",
128         REVISION
129     );
130     let response = reqwest::blocking::get(&url)?.error_for_status()?;
131     let progress = Progress::new(response);
132     let decoder = GzDecoder::new(progress);
133     let mut archive = Archive::new(decoder);
134     let prefix = format!("rust-{}", REVISION);
135 
136     let tests_rust = Path::new("tests/rust");
137     if tests_rust.exists() {
138         fs::remove_dir_all(tests_rust)?;
139     }
140 
141     for entry in archive.entries()? {
142         let mut entry = entry?;
143         let path = entry.path()?;
144         if path == Path::new("pax_global_header") {
145             continue;
146         }
147         let relative = path.strip_prefix(&prefix)?;
148         let out = tests_rust.join(relative);
149         entry.unpack(&out)?;
150     }
151 
152     fs::write("tests/rust/COMMIT", REVISION)?;
153     Ok(())
154 }
155