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 = "e100ec5bc7cd768ec17d75448b29c9ab4a39272b";
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     // Clippy lint lists represented as expressions
50     "src/tools/clippy/clippy_lints/src/lib.deprecated.rs",
51     "src/tools/clippy/clippy_lints/src/lib.register_all.rs",
52     "src/tools/clippy/clippy_lints/src/lib.register_cargo.rs",
53     "src/tools/clippy/clippy_lints/src/lib.register_complexity.rs",
54     "src/tools/clippy/clippy_lints/src/lib.register_correctness.rs",
55     "src/tools/clippy/clippy_lints/src/lib.register_internal.rs",
56     "src/tools/clippy/clippy_lints/src/lib.register_lints.rs",
57     "src/tools/clippy/clippy_lints/src/lib.register_nursery.rs",
58     "src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs",
59     "src/tools/clippy/clippy_lints/src/lib.register_perf.rs",
60     "src/tools/clippy/clippy_lints/src/lib.register_restriction.rs",
61     "src/tools/clippy/clippy_lints/src/lib.register_style.rs",
62     "src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs",
63 
64     // Not actually test cases
65     "src/test/rustdoc-ui/test-compile-fail2.rs",
66     "src/test/rustdoc-ui/test-compile-fail3.rs",
67     "src/test/ui/json-bom-plus-crlf-multifile-aux.rs",
68     "src/test/ui/lint/expansion-time-include.rs",
69     "src/test/ui/macros/auxiliary/macro-comma-support.rs",
70     "src/test/ui/macros/auxiliary/macro-include-items-expr.rs",
71     "src/test/ui/macros/include-single-expr-helper.rs",
72     "src/test/ui/macros/include-single-expr-helper-1.rs",
73     "src/test/ui/parser/issues/auxiliary/issue-21146-inc.rs",
74 ];
75 
base_dir_filter(entry: &DirEntry) -> bool76 pub fn base_dir_filter(entry: &DirEntry) -> bool {
77     let path = entry.path();
78     if path.is_dir() {
79         return true; // otherwise walkdir does not visit the files
80     }
81     if path.extension().map_or(true, |e| e != "rs") {
82         return false;
83     }
84 
85     let mut path_string = path.to_string_lossy();
86     if cfg!(windows) {
87         path_string = path_string.replace('\\', "/").into();
88     }
89     let path = if let Some(path) = path_string.strip_prefix("tests/rust/") {
90         path
91     } else {
92         panic!("unexpected path in Rust dist: {}", path_string);
93     };
94 
95     if path.starts_with("src/test/compile-fail") || path.starts_with("src/test/rustfix") {
96         return false;
97     }
98 
99     if path.starts_with("src/test/ui") {
100         let stderr_path = entry.path().with_extension("stderr");
101         if stderr_path.exists() {
102             // Expected to fail in some way
103             return false;
104         }
105     }
106 
107     !EXCLUDE.contains(&path)
108 }
109 
110 #[allow(dead_code)]
edition(path: &Path) -> &'static str111 pub fn edition(path: &Path) -> &'static str {
112     if path.ends_with("dyn-2015-no-warnings-without-lints.rs") {
113         "2015"
114     } else {
115         "2018"
116     }
117 }
118 
clone_rust()119 pub fn clone_rust() {
120     let needs_clone = match fs::read_to_string("tests/rust/COMMIT") {
121         Err(_) => true,
122         Ok(contents) => contents.trim() != REVISION,
123     };
124     if needs_clone {
125         download_and_unpack().unwrap();
126     }
127     let mut missing = String::new();
128     let test_src = Path::new("tests/rust");
129     for exclude in EXCLUDE {
130         if !test_src.join(exclude).exists() {
131             missing += "\ntests/rust/";
132             missing += exclude;
133         }
134     }
135     if !missing.is_empty() {
136         panic!("excluded test file does not exist:{}\n", missing);
137     }
138 }
139 
download_and_unpack() -> Result<()>140 fn download_and_unpack() -> Result<()> {
141     let url = format!(
142         "https://github.com/rust-lang/rust/archive/{}.tar.gz",
143         REVISION
144     );
145     let response = reqwest::blocking::get(&url)?.error_for_status()?;
146     let progress = Progress::new(response);
147     let decoder = GzDecoder::new(progress);
148     let mut archive = Archive::new(decoder);
149     let prefix = format!("rust-{}", REVISION);
150 
151     let tests_rust = Path::new("tests/rust");
152     if tests_rust.exists() {
153         fs::remove_dir_all(tests_rust)?;
154     }
155 
156     for entry in archive.entries()? {
157         let mut entry = entry?;
158         let path = entry.path()?;
159         if path == Path::new("pax_global_header") {
160             continue;
161         }
162         let relative = path.strip_prefix(&prefix)?;
163         let out = tests_rust.join(relative);
164         entry.unpack(&out)?;
165     }
166 
167     fs::write("tests/rust/COMMIT", REVISION)?;
168     Ok(())
169 }
170