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