Adds pass command to clif-util. (#487)
* Adds pass command to clif-util.
This commit is contained in:
committed by
Dan Gohman
parent
17bb62c16c
commit
59b83912ba
@@ -131,17 +131,18 @@ fn worker_thread(
|
||||
// The receiver should always be present for this as long as we have jobs.
|
||||
replies.send(Reply::Starting { jobid, thread_num }).unwrap();
|
||||
|
||||
let result = catch_unwind(|| runone::run(path.as_path())).unwrap_or_else(|e| {
|
||||
// The test panicked, leaving us a `Box<Any>`.
|
||||
// Panics are usually strings.
|
||||
if let Some(msg) = e.downcast_ref::<String>() {
|
||||
Err(format!("panicked in worker #{}: {}", thread_num, msg))
|
||||
} else if let Some(msg) = e.downcast_ref::<&'static str>() {
|
||||
Err(format!("panicked in worker #{}: {}", thread_num, msg))
|
||||
} else {
|
||||
Err(format!("panicked in worker #{}", thread_num))
|
||||
}
|
||||
});
|
||||
let result = catch_unwind(|| runone::run(path.as_path(), None, None))
|
||||
.unwrap_or_else(|e| {
|
||||
// The test panicked, leaving us a `Box<Any>`.
|
||||
// Panics are usually strings.
|
||||
if let Some(msg) = e.downcast_ref::<String>() {
|
||||
Err(format!("panicked in worker #{}: {}", thread_num, msg))
|
||||
} else if let Some(msg) = e.downcast_ref::<&'static str>() {
|
||||
Err(format!("panicked in worker #{}: {}", thread_num, msg))
|
||||
} else {
|
||||
Err(format!("panicked in worker #{}", thread_num))
|
||||
}
|
||||
});
|
||||
|
||||
if let Err(ref msg) = result {
|
||||
error!("FAIL: {}", msg);
|
||||
|
||||
@@ -79,6 +79,24 @@ pub fn run(verbose: bool, files: &[String]) -> TestResult {
|
||||
runner.run()
|
||||
}
|
||||
|
||||
/// Used for 'pass' subcommand.
|
||||
/// Commands are interpreted as test and executed.
|
||||
///
|
||||
/// Directories are scanned recursively for test cases ending in `.clif`.
|
||||
///
|
||||
pub fn run_passes(verbose: bool, passes: &[String], target: &str, file: &String) -> TestResult {
|
||||
let mut runner = TestRunner::new(verbose);
|
||||
|
||||
let path = Path::new(file);
|
||||
if path.is_file() {
|
||||
runner.push_test(path);
|
||||
} else {
|
||||
runner.push_dir(path);
|
||||
}
|
||||
|
||||
runner.run_passes(passes, target)
|
||||
}
|
||||
|
||||
/// Create a new subcommand trait object to match `parsed.command`.
|
||||
///
|
||||
/// This function knows how to create all of the possible `test <foo>` commands that can appear in
|
||||
|
||||
@@ -30,6 +30,12 @@ enum State {
|
||||
Done(TestResult),
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
pub enum IsPass {
|
||||
Pass,
|
||||
NotPass,
|
||||
}
|
||||
|
||||
impl QueueEntry {
|
||||
pub fn path(&self) -> &Path {
|
||||
self.path.as_path()
|
||||
@@ -118,7 +124,7 @@ impl TestRunner {
|
||||
|
||||
/// Scan any directories pushed so far.
|
||||
/// Push any potential test cases found.
|
||||
pub fn scan_dirs(&mut self) {
|
||||
pub fn scan_dirs(&mut self, pass_status: IsPass) {
|
||||
// This recursive search tries to minimize statting in a directory hierarchy containing
|
||||
// mostly test cases.
|
||||
//
|
||||
@@ -164,8 +170,12 @@ impl TestRunner {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Get the new jobs running before moving on to the next directory.
|
||||
self.schedule_jobs();
|
||||
if pass_status == IsPass::Pass {
|
||||
continue;
|
||||
} else {
|
||||
// Get the new jobs running before moving on to the next directory.
|
||||
self.schedule_jobs();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,7 +213,7 @@ impl TestRunner {
|
||||
} else {
|
||||
// Run test synchronously.
|
||||
self.tests[jobid].state = State::Running;
|
||||
let result = runone::run(self.tests[jobid].path());
|
||||
let result = runone::run(self.tests[jobid].path(), None, None);
|
||||
self.finish_job(jobid, result);
|
||||
}
|
||||
self.new_tests = jobid + 1;
|
||||
@@ -215,6 +225,20 @@ impl TestRunner {
|
||||
}
|
||||
}
|
||||
|
||||
/// Schedule any new job to run for the pass command.
|
||||
fn schedule_pass_job(&mut self, passes: &[String], target: &str) {
|
||||
self.tests[0].state = State::Running;
|
||||
let result: Result<time::Duration, String>;
|
||||
|
||||
let specified_target = match target {
|
||||
"" => None,
|
||||
targ => Some(targ),
|
||||
};
|
||||
|
||||
result = runone::run(self.tests[0].path(), Some(passes), specified_target);
|
||||
self.finish_job(0, result);
|
||||
}
|
||||
|
||||
/// Report the end of a job.
|
||||
fn finish_job(&mut self, jobid: usize, result: TestResult) {
|
||||
assert_eq!(self.tests[jobid].state, State::Running);
|
||||
@@ -331,10 +355,26 @@ impl TestRunner {
|
||||
/// Scan pushed directories for tests and run them.
|
||||
pub fn run(&mut self) -> TestResult {
|
||||
let started = time::Instant::now();
|
||||
self.scan_dirs();
|
||||
self.scan_dirs(IsPass::NotPass);
|
||||
self.schedule_jobs();
|
||||
self.drain_threads();
|
||||
self.report_slow_tests();
|
||||
self.drain_threads();
|
||||
|
||||
println!("{} tests", self.tests.len());
|
||||
match self.errors {
|
||||
0 => Ok(started.elapsed()),
|
||||
1 => Err("1 failure".to_string()),
|
||||
n => Err(format!("{} failures", n)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Scan pushed directories for tests and run specified passes from commandline on them.
|
||||
pub fn run_passes(&mut self, passes: &[String], target: &str) -> TestResult {
|
||||
let started = time::Instant::now();
|
||||
self.scan_dirs(IsPass::Pass);
|
||||
self.schedule_pass_job(passes, target);
|
||||
self.report_slow_tests();
|
||||
|
||||
println!("{} tests", self.tests.len());
|
||||
match self.errors {
|
||||
0 => Ok(started.elapsed()),
|
||||
|
||||
@@ -27,12 +27,12 @@ fn read_to_string<P: AsRef<Path>>(path: P) -> io::Result<String> {
|
||||
/// Load `path` and run the test in it.
|
||||
///
|
||||
/// If running this test causes a panic, it will propagate as normal.
|
||||
pub fn run(path: &Path) -> TestResult {
|
||||
pub fn run(path: &Path, passes: Option<&[String]>, target: Option<&str>) -> TestResult {
|
||||
let _tt = timing::process_file();
|
||||
info!("---\nFile: {}", path.to_string_lossy());
|
||||
let started = time::Instant::now();
|
||||
let buffer = read_to_string(path).map_err(|e| e.to_string())?;
|
||||
let testfile = parse_test(&buffer).map_err(|e| e.to_string())?;
|
||||
let testfile = parse_test(&buffer, passes, target).map_err(|e| e.to_string())?;
|
||||
if testfile.functions.is_empty() {
|
||||
return Err("no functions found".to_string());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user