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
8 pub use crate::function_runner::TestFileCompiler;
9 use crate::runner::TestRunner;
10 use cranelift_reader::TestCommand;
11 use std::path::Path;
12
13 mod concurrent;
14 pub mod function_runner;
15 mod match_directive;
16 mod runner;
17 mod runone;
18 mod subtest;
19
20 mod test_alias_analysis;
21 mod test_cat;
22 mod test_compile;
23 mod test_domtree;
24 mod test_inline;
25 mod test_interpret;
26 mod test_legalizer;
27 mod test_optimize;
28 mod test_print_cfg;
29 mod test_run;
30 mod test_safepoint;
31 mod test_unwind;
32 mod 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 ///
run(verbose: bool, report_times: bool, files: &[String]) -> anyhow::Result<()>43 pub 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 ///
run_passes( verbose: bool, report_times: bool, passes: &[String], target: &str, file: &str, ) -> anyhow::Result<()>63 pub 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.
new_subtest(parsed: &TestCommand) -> anyhow::Result<Box<dyn subtest::SubTest>>87 fn 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
pretty_anyhow_error( func: &cranelift_codegen::ir::Function, err: cranelift_codegen::CodegenError, ) -> anyhow::Error106 fn 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 }
113