|
| 1 | +//! Tidy check to ensure that all target specific tests (those that require a `--target` flag) |
| 2 | +//! also require the pre-requisite LLVM components to run. |
| 3 | +
|
| 4 | +use std::collections::BTreeMap; |
| 5 | +use std::path::Path; |
| 6 | + |
| 7 | +const COMMENT: &str = "//"; |
| 8 | +const LLVM_COMPONENTS_HEADER: &str = "needs-llvm-components:"; |
| 9 | +const COMPILE_FLAGS_HEADER: &str = "compile-flags:"; |
| 10 | + |
| 11 | +/// Iterate through compiletest headers in a test contents. |
| 12 | +/// |
| 13 | +/// Adjusted from compiletest/src/header.rs. |
| 14 | +fn iter_header<'a>(contents: &'a str, it: &mut dyn FnMut(Option<&'a str>, &'a str)) { |
| 15 | + for ln in contents.lines() { |
| 16 | + let ln = ln.trim(); |
| 17 | + if ln.starts_with(COMMENT) && ln[COMMENT.len()..].trim_start().starts_with('[') { |
| 18 | + if let Some(close_brace) = ln.find(']') { |
| 19 | + let open_brace = ln.find('[').unwrap(); |
| 20 | + let lncfg = &ln[open_brace + 1..close_brace]; |
| 21 | + it(Some(lncfg), ln[(close_brace + 1)..].trim_start()); |
| 22 | + } else { |
| 23 | + panic!("malformed condition directive: expected `//[foo]`, found `{}`", ln) |
| 24 | + } |
| 25 | + } else if ln.starts_with(COMMENT) { |
| 26 | + it(None, ln[COMMENT.len()..].trim_start()); |
| 27 | + } |
| 28 | + } |
| 29 | +} |
| 30 | + |
| 31 | +#[derive(Default, Debug)] |
| 32 | +struct RevisionInfo<'a> { |
| 33 | + target_arch: Option<&'a str>, |
| 34 | + llvm_components: Option<Vec<&'a str>>, |
| 35 | +} |
| 36 | + |
| 37 | +pub fn check(path: &Path, bad: &mut bool) { |
| 38 | + let tests = path.join("test"); |
| 39 | + super::walk( |
| 40 | + &tests, |
| 41 | + &mut |path| path.extension().map(|p| p == "rs") == Some(false), |
| 42 | + &mut |entry, content| { |
| 43 | + let file = entry.path().display(); |
| 44 | + let mut header_map = BTreeMap::new(); |
| 45 | + iter_header(content, &mut |cfg, directive| { |
| 46 | + if let Some(value) = directive.strip_prefix(LLVM_COMPONENTS_HEADER) { |
| 47 | + let info = header_map.entry(cfg).or_insert(RevisionInfo::default()); |
| 48 | + let comp_vec = info.llvm_components.get_or_insert(Vec::new()); |
| 49 | + for component in value.split(' ') { |
| 50 | + let component = component.trim(); |
| 51 | + if !component.is_empty() { |
| 52 | + comp_vec.push(component); |
| 53 | + } |
| 54 | + } |
| 55 | + } else if directive.starts_with(COMPILE_FLAGS_HEADER) { |
| 56 | + let compile_flags = &directive[COMPILE_FLAGS_HEADER.len()..]; |
| 57 | + if let Some((_, v)) = compile_flags.split_once("--target") { |
| 58 | + if let Some((arch, _)) = |
| 59 | + v.trim_start_matches(|c| c == ' ' || c == '=').split_once("-") |
| 60 | + { |
| 61 | + let info = header_map.entry(cfg).or_insert(RevisionInfo::default()); |
| 62 | + info.target_arch.replace(arch); |
| 63 | + } else { |
| 64 | + eprintln!("{}: seems to have a malformed --target value", file); |
| 65 | + *bad = true; |
| 66 | + } |
| 67 | + } |
| 68 | + } |
| 69 | + }); |
| 70 | + for (rev, RevisionInfo { target_arch, llvm_components }) in &header_map { |
| 71 | + let rev = rev.unwrap_or("[unspecified]"); |
| 72 | + match (target_arch, llvm_components) { |
| 73 | + (None, None) => {} |
| 74 | + (Some(_), None) => { |
| 75 | + eprintln!( |
| 76 | + "{}: revision {} should specify `{}` as it has `--target` set", |
| 77 | + file, rev, LLVM_COMPONENTS_HEADER |
| 78 | + ); |
| 79 | + *bad = true; |
| 80 | + } |
| 81 | + (None, Some(_)) => { |
| 82 | + eprintln!( |
| 83 | + "{}: revision {} should not specify `{}` as it doesn't need `--target`", |
| 84 | + file, rev, LLVM_COMPONENTS_HEADER |
| 85 | + ); |
| 86 | + *bad = true; |
| 87 | + } |
| 88 | + (Some(_), Some(_)) => { |
| 89 | + // FIXME: check specified components against the target architectures we |
| 90 | + // gathered. |
| 91 | + } |
| 92 | + } |
| 93 | + } |
| 94 | + }, |
| 95 | + ); |
| 96 | +} |
0 commit comments