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 /// 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 /// 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. 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 106 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