blob: cae96f593199e24665f7b9b232b3d446971122be [file] [log] [blame]
use std::fs;
use std::path::Path;
pub struct MiroptTestFile {
pub expected_file: std::path::PathBuf,
pub from_file: String,
pub to_file: Option<String>,
}
pub struct MiroptTest {
pub run_filecheck: bool,
pub suffix: String,
pub files: Vec<MiroptTestFile>,
/// Vec of passes under test to be dumped
pub passes: Vec<String>,
}
pub enum PanicStrategy {
Unwind,
Abort,
}
fn output_file_suffix(testfile: &Path, bit_width: u32, panic_strategy: PanicStrategy) -> String {
let mut each_bit_width = false;
let mut each_panic_strategy = false;
for line in fs::read_to_string(testfile).unwrap().lines() {
if line == "// EMIT_MIR_FOR_EACH_BIT_WIDTH" {
each_bit_width = true;
}
if line == "// EMIT_MIR_FOR_EACH_PANIC_STRATEGY" {
each_panic_strategy = true;
}
}
let mut suffix = String::new();
if each_bit_width {
suffix.push_str(&format!(".{}bit", bit_width));
}
if each_panic_strategy {
match panic_strategy {
PanicStrategy::Unwind => suffix.push_str(".panic-unwind"),
PanicStrategy::Abort => suffix.push_str(".panic-abort"),
}
}
suffix
}
pub fn files_for_miropt_test(
testfile: &std::path::Path,
bit_width: u32,
panic_strategy: PanicStrategy,
) -> MiroptTest {
let mut out = Vec::new();
let test_file_contents = fs::read_to_string(&testfile).unwrap();
let test_dir = testfile.parent().unwrap();
let test_crate = testfile.file_stem().unwrap().to_str().unwrap().replace('-', "_");
let suffix = output_file_suffix(testfile, bit_width, panic_strategy);
let mut run_filecheck = true;
let mut passes = Vec::new();
for l in test_file_contents.lines() {
if l.starts_with("// skip-filecheck") {
run_filecheck = false;
continue;
}
if l.starts_with("// EMIT_MIR ") {
let test_name = l.trim_start_matches("// EMIT_MIR ").trim();
let mut test_names = test_name.split(' ');
// sometimes we specify two files so that we get a diff between the two files
let test_name = test_names.next().unwrap();
let mut expected_file;
let from_file;
let to_file;
if test_name.ends_with(".diff") {
let trimmed = test_name.trim_end_matches(".diff");
passes.push(trimmed.split('.').last().unwrap().to_owned());
let test_against = format!("{}.after.mir", trimmed);
from_file = format!("{}.before.mir", trimmed);
expected_file = format!("{}{}.diff", trimmed, suffix);
assert!(test_names.next().is_none(), "two mir pass names specified for MIR diff");
to_file = Some(test_against);
} else if let Some(first_pass) = test_names.next() {
let second_pass = test_names.next().unwrap();
if let Some((first_pass_name, _)) = first_pass.split_once('.') {
passes.push(first_pass_name.to_owned());
}
if let Some((second_pass_name, _)) = second_pass.split_once('.') {
passes.push(second_pass_name.to_owned());
}
assert!(test_names.next().is_none(), "three mir pass names specified for MIR diff");
expected_file =
format!("{}{}.{}-{}.diff", test_name, suffix, first_pass, second_pass);
let second_file = format!("{}.{}.mir", test_name, second_pass);
from_file = format!("{}.{}.mir", test_name, first_pass);
to_file = Some(second_file);
} else {
let ext_re = regex::Regex::new(r#"(\.(mir|dot|html))$"#).unwrap();
let cap = ext_re
.captures_iter(test_name)
.next()
.expect("test_name has an invalid extension");
let extension = cap.get(1).unwrap().as_str();
expected_file =
format!("{}{}{}", test_name.trim_end_matches(extension), suffix, extension,);
from_file = test_name.to_string();
assert!(test_names.next().is_none(), "two mir pass names specified for MIR dump");
to_file = None;
// the pass name is the third to last string in the test name
// this gets pushed into passes
passes.push(
test_name.split('.').rev().nth(2).expect("invalid test format").to_string(),
);
};
if !expected_file.starts_with(&test_crate) {
expected_file = format!("{}.{}", test_crate, expected_file);
}
let expected_file = test_dir.join(expected_file);
out.push(MiroptTestFile { expected_file, from_file, to_file });
}
}
MiroptTest { run_filecheck, suffix, files: out, passes }
}