cranelift_filetests/
lib.rs

1//! File tests.
2//!
3//! This crate contains the main test driver as well as implementations of the
4//! available filetest commands.
5
6#![deny(missing_docs)]
7
8pub use crate::function_runner::TestFileCompiler;
9use crate::runner::TestRunner;
10use cranelift_reader::TestCommand;
11use std::path::Path;
12
13mod concurrent;
14pub mod function_runner;
15mod match_directive;
16mod runner;
17mod runone;
18mod subtest;
19
20mod test_alias_analysis;
21mod test_cat;
22mod test_compile;
23mod test_domtree;
24mod test_interpret;
25mod test_legalizer;
26mod test_optimize;
27mod test_print_cfg;
28mod test_run;
29mod test_safepoint;
30mod test_unwind;
31mod test_verifier;
32
33/// Main entry point for `clif-util test`.
34///
35/// Take a list of filenames which can be either `.clif` files or directories.
36///
37/// Files are interpreted as test cases and executed immediately.
38///
39/// Directories are scanned recursively for test cases ending in `.clif`. These test cases are
40/// executed on background threads.
41///
42pub fn run(verbose: bool, report_times: bool, files: &[String]) -> anyhow::Result<()> {
43    let mut runner = TestRunner::new(verbose, report_times);
44
45    for path in files.iter().map(Path::new) {
46        if path.is_file() {
47            runner.push_test(path);
48        } else {
49            runner.push_dir(path);
50        }
51    }
52
53    runner.start_threads();
54    runner.run()
55}
56
57/// Used for 'pass' subcommand.
58/// Commands are interpreted as test and executed.
59///
60/// Directories are scanned recursively for test cases ending in `.clif`.
61///
62pub fn run_passes(
63    verbose: bool,
64    report_times: bool,
65    passes: &[String],
66    target: &str,
67    file: &str,
68) -> anyhow::Result<()> {
69    let mut runner = TestRunner::new(verbose, report_times);
70
71    let path = Path::new(file);
72    if path == Path::new("-") || path.is_file() {
73        runner.push_test(path);
74    } else {
75        runner.push_dir(path);
76    }
77
78    runner.start_threads();
79    runner.run_passes(passes, target)
80}
81
82/// Create a new subcommand trait object to match `parsed.command`.
83///
84/// This function knows how to create all of the possible `test <foo>` commands that can appear in
85/// a `.clif` test file.
86fn new_subtest(parsed: &TestCommand) -> anyhow::Result<Box<dyn subtest::SubTest>> {
87    match parsed.command {
88        "alias-analysis" => test_alias_analysis::subtest(parsed),
89        "cat" => test_cat::subtest(parsed),
90        "compile" => test_compile::subtest(parsed),
91        "domtree" => test_domtree::subtest(parsed),
92        "interpret" => test_interpret::subtest(parsed),
93        "legalizer" => test_legalizer::subtest(parsed),
94        "optimize" => test_optimize::subtest(parsed),
95        "print-cfg" => test_print_cfg::subtest(parsed),
96        "run" => test_run::subtest(parsed),
97        "safepoint" => test_safepoint::subtest(parsed),
98        "unwind" => test_unwind::subtest(parsed),
99        "verifier" => test_verifier::subtest(parsed),
100        _ => anyhow::bail!("unknown test command '{}'", parsed.command),
101    }
102}
103
104fn pretty_anyhow_error(
105    func: &cranelift_codegen::ir::Function,
106    err: cranelift_codegen::CodegenError,
107) -> anyhow::Error {
108    let s = cranelift_codegen::print_errors::pretty_error(func, err);
109    anyhow::anyhow!("{}", s)
110}