Spin up one worker thread per cpu, and run filetests on all of them. Use a reorder buffer in Runner to make sure results are still reported in order. Individual test files given as command line arguments are still run synchronously for easier debugging. Only directories are run on worker threads. The recursive directory traversal is still happening on the main thread. Use a heartbeat thread to send ticks on the reply channel every second, and use the ticks to detect tests that are stuck. When Receiver::recv_timeout() is stabilized, we can probably get rid of the heartbeat thread. Catch panics on the worker threads and report them as test failures.
85 lines
2.0 KiB
Rust
85 lines
2.0 KiB
Rust
|
|
extern crate cretonne;
|
|
extern crate cton_reader;
|
|
extern crate docopt;
|
|
extern crate rustc_serialize;
|
|
extern crate filecheck;
|
|
extern crate num_cpus;
|
|
|
|
use cretonne::VERSION;
|
|
use docopt::Docopt;
|
|
use std::io::{self, Write};
|
|
use std::process;
|
|
|
|
mod utils;
|
|
mod filetest;
|
|
mod cat;
|
|
mod print_cfg;
|
|
mod rsfilecheck;
|
|
|
|
const USAGE: &'static str = "
|
|
Cretonne code generator utility
|
|
|
|
Usage:
|
|
cton-util test <file>...
|
|
cton-util cat <file>...
|
|
cton-util filecheck [-v] <file>
|
|
cton-util print-cfg <file>...
|
|
cton-util --help | --version
|
|
|
|
Options:
|
|
-v, --verbose be more verbose
|
|
-h, --help print this help message
|
|
--version print the Cretonne version
|
|
|
|
";
|
|
|
|
#[derive(RustcDecodable, Debug)]
|
|
struct Args {
|
|
cmd_test: bool,
|
|
cmd_cat: bool,
|
|
cmd_filecheck: bool,
|
|
cmd_print_cfg: bool,
|
|
arg_file: Vec<String>,
|
|
flag_verbose: bool,
|
|
}
|
|
|
|
/// A command either succeeds or fails with an error message.
|
|
pub type CommandResult = Result<(), String>;
|
|
|
|
/// Parse the command line arguments and run the requested command.
|
|
fn cton_util() -> CommandResult {
|
|
// Parse comand line arguments.
|
|
let args: Args = Docopt::new(USAGE)
|
|
.and_then(|d| {
|
|
d.help(true)
|
|
.version(Some(format!("Cretonne {}", VERSION)))
|
|
.decode()
|
|
})
|
|
.unwrap_or_else(|e| e.exit());
|
|
|
|
// Find the sub-command to execute.
|
|
if args.cmd_test {
|
|
filetest::run(args.arg_file)
|
|
} else if args.cmd_cat {
|
|
cat::run(args.arg_file)
|
|
} else if args.cmd_filecheck {
|
|
rsfilecheck::run(args.arg_file, args.flag_verbose)
|
|
} else if args.cmd_print_cfg {
|
|
print_cfg::run(args.arg_file)
|
|
} else {
|
|
// Debugging / shouldn't happen with proper command line handling above.
|
|
Err(format!("Unhandled args: {:?}", args))
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
if let Err(mut msg) = cton_util() {
|
|
if !msg.ends_with('\n') {
|
|
msg.push('\n');
|
|
}
|
|
io::stderr().write(msg.as_bytes()).unwrap();
|
|
process::exit(1);
|
|
}
|
|
}
|