From 665555d58f2aa3c1d8aecd7b34392bde6c41b20d Mon Sep 17 00:00:00 2001 From: lpy Date: Wed, 12 Feb 2014 23:39:21 +0800 Subject: return value/use extra::test::black_box in benchmarks --- src/libstd/io/buffered.rs | 4 ++-- src/libstd/mem.rs | 12 ++++++------ src/libstd/rt/global_heap.rs | 4 ++-- src/libstd/str.rs | 6 +++--- src/libstd/vec.rs | 19 +++++++++++-------- 5 files changed, 24 insertions(+), 21 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 231cf6592eb..fbed53ee30d 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -565,14 +565,14 @@ mod test { #[bench] fn bench_buffered_reader(bh: &mut Harness) { bh.iter(|| { - BufferedReader::new(NullStream); + BufferedReader::new(NullStream) }); } #[bench] fn bench_buffered_writer(bh: &mut Harness) { bh.iter(|| { - BufferedWriter::new(NullStream); + BufferedWriter::new(NullStream) }); } diff --git a/src/libstd/mem.rs b/src/libstd/mem.rs index 09d2db329ca..ee05d6a704b 100644 --- a/src/libstd/mem.rs +++ b/src/libstd/mem.rs @@ -292,7 +292,7 @@ mod bench { let s = Struct { field: 10 }; let t = &s as &Trait; bh.iter(|| { - t.method(); + t.method() }); } @@ -300,7 +300,7 @@ mod bench { fn trait_static_method_call(bh: &mut BenchHarness) { let s = Struct { field: 10 }; bh.iter(|| { - s.method(); + s.method() }); } @@ -310,10 +310,10 @@ mod bench { fn match_option_some(bh: &mut BenchHarness) { let x = Some(10); bh.iter(|| { - let _q = match x { + match x { Some(y) => y, None => 11 - }; + } }); } @@ -321,10 +321,10 @@ mod bench { fn match_vec_pattern(bh: &mut BenchHarness) { let x = [1,2,3,4,5,6]; bh.iter(|| { - let _q = match x { + match x { [1,2,3,..] => 10, _ => 11 - }; + } }); } } diff --git a/src/libstd/rt/global_heap.rs b/src/libstd/rt/global_heap.rs index 4bce16706ee..ab279fd3102 100644 --- a/src/libstd/rt/global_heap.rs +++ b/src/libstd/rt/global_heap.rs @@ -112,14 +112,14 @@ mod bench { #[bench] fn alloc_owned_small(bh: &mut BenchHarness) { bh.iter(|| { - ~10; + ~10 }) } #[bench] fn alloc_owned_big(bh: &mut BenchHarness) { bh.iter(|| { - ~[10, ..1000]; + ~[10, ..1000] }) } } diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 0d263d94ccf..063182ff0e1 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -4357,7 +4357,7 @@ mod bench { assert_eq!(100, s.len()); bh.iter(|| { - let _ = is_utf8(s); + is_utf8(s) }); } @@ -4366,7 +4366,7 @@ mod bench { let s = bytes!("πŒ€πŒ–πŒ‹πŒ„πŒ‘πŒ‰ΰΈ›ΰΈ£Ψ―ΩˆΩ„Ψ© Ψ§Ω„ΩƒΩˆΩŠΨͺΰΈ—ΰΈ¨ΰΉ„ΰΈ—ΰΈ’δΈ­εŽπ…πŒΏπŒ»π†πŒΉπŒ»πŒ°"); assert_eq!(100, s.len()); bh.iter(|| { - let _ = is_utf8(s); + is_utf8(s) }); } @@ -4409,7 +4409,7 @@ mod bench { #[bench] fn bench_with_capacity(bh: &mut BenchHarness) { bh.iter(|| { - let _ = with_capacity(100); + with_capacity(100) }); } diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index c67b19933d3..cfe2ad5a08a 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -4428,6 +4428,7 @@ mod bench { let mut vec: ~[uint] = ~[0u]; bh.iter(|| { vec.push(0); + &vec }) } @@ -4435,7 +4436,7 @@ mod bench { fn starts_with_same_vector(bh: &mut BenchHarness) { let vec: ~[uint] = vec::from_fn(100, |i| i); bh.iter(|| { - vec.starts_with(vec); + vec.starts_with(vec) }) } @@ -4443,7 +4444,7 @@ mod bench { fn starts_with_single_element(bh: &mut BenchHarness) { let vec: ~[uint] = ~[0u]; bh.iter(|| { - vec.starts_with(vec); + vec.starts_with(vec) }) } @@ -4453,7 +4454,7 @@ mod bench { let mut match_vec: ~[uint] = vec::from_fn(99, |i| i); match_vec.push(0); bh.iter(|| { - vec.starts_with(match_vec); + vec.starts_with(match_vec) }) } @@ -4461,7 +4462,7 @@ mod bench { fn ends_with_same_vector(bh: &mut BenchHarness) { let vec: ~[uint] = vec::from_fn(100, |i| i); bh.iter(|| { - vec.ends_with(vec); + vec.ends_with(vec) }) } @@ -4469,7 +4470,7 @@ mod bench { fn ends_with_single_element(bh: &mut BenchHarness) { let vec: ~[uint] = ~[0u]; bh.iter(|| { - vec.ends_with(vec); + vec.ends_with(vec) }) } @@ -4479,7 +4480,7 @@ mod bench { let mut match_vec: ~[uint] = vec::from_fn(100, |i| i); match_vec[0] = 200; bh.iter(|| { - vec.starts_with(match_vec); + vec.starts_with(match_vec) }) } @@ -4487,7 +4488,7 @@ mod bench { fn contains_last_element(bh: &mut BenchHarness) { let vec: ~[uint] = vec::from_fn(100, |i| i); bh.iter(|| { - vec.contains(&99u); + vec.contains(&99u) }) } @@ -4507,13 +4508,14 @@ mod bench { ptr::set_memory(vp, 0, 1024); v.set_len(1024); } + v }); } #[bench] fn zero_1kb_fixed_repeat(bh: &mut BenchHarness) { bh.iter(|| { - let _v: ~[u8] = ~[0u8, ..1024]; + ~[0u8, ..1024] }); } @@ -4542,6 +4544,7 @@ mod bench { for x in v.mut_iter() { *x = 0; } + v }); } -- cgit 1.4.1-3-g733a5 From ee2a888860ea496b5a972ed35fb742b4ae008233 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 12 Feb 2014 10:25:09 -0800 Subject: extra: Capture stdout/stderr of tests by default When tests fail, their stdout and stderr is printed as part of the summary, but this helps suppress failure messages from #[should_fail] tests and generally clean up the output of the test runner. --- src/compiletest/header.rs | 12 +++++ src/compiletest/runtest.rs | 7 ++- src/libextra/test.rs | 85 +++++++++++++++++++------------ src/libstd/io/comm_adapters.rs | 6 +++ src/test/run-fail/run-unexported-tests.rs | 1 + src/test/run-fail/test-fail.rs | 1 + 6 files changed, 78 insertions(+), 34 deletions(-) (limited to 'src/libstd') diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index 0c965b7c6c3..38c1162f636 100644 --- a/src/compiletest/header.rs +++ b/src/compiletest/header.rs @@ -30,6 +30,8 @@ pub struct TestProps { check_lines: ~[~str], // Flag to force a crate to be built with the host architecture force_host: bool, + // Check stdout for error-pattern output as well as stderr + check_stdout: bool, } // Load any test directives embedded in the file @@ -42,6 +44,7 @@ pub fn load_props(testfile: &Path) -> TestProps { let mut debugger_cmds = ~[]; let mut check_lines = ~[]; let mut force_host = false; + let mut check_stdout = false; iter_header(testfile, |ln| { match parse_error_pattern(ln) { Some(ep) => error_patterns.push(ep), @@ -60,6 +63,10 @@ pub fn load_props(testfile: &Path) -> TestProps { force_host = parse_force_host(ln); } + if !check_stdout { + check_stdout = parse_check_stdout(ln); + } + match parse_aux_build(ln) { Some(ab) => { aux_builds.push(ab); } None => {} @@ -91,6 +98,7 @@ pub fn load_props(testfile: &Path) -> TestProps { debugger_cmds: debugger_cmds, check_lines: check_lines, force_host: force_host, + check_stdout: check_stdout, }; } @@ -155,6 +163,10 @@ fn parse_force_host(line: &str) -> bool { parse_name_directive(line, "force-host") } +fn parse_check_stdout(line: &str) -> bool { + parse_name_directive(line, "check-stdout") +} + fn parse_exec_env(line: &str) -> Option<(~str, ~str)> { parse_name_value_directive(line, ~"exec-env").map(|nv| { // nv is either FOO or FOO=BAR diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index a2c61352e6f..8b45d987864 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -452,7 +452,12 @@ fn check_error_patterns(props: &TestProps, let mut next_err_idx = 0u; let mut next_err_pat = &props.error_patterns[next_err_idx]; let mut done = false; - for line in ProcRes.stderr.lines() { + let output_to_check = if props.check_stdout { + ProcRes.stdout + ProcRes.stderr + } else { + ProcRes.stderr.clone() + }; + for line in output_to_check.lines() { if line.contains(*next_err_pat) { debug!("found error pattern {}", *next_err_pat); next_err_idx += 1u; diff --git a/src/libextra/test.rs b/src/libextra/test.rs index 85da41911c9..df13538b4bc 100644 --- a/src/libextra/test.rs +++ b/src/libextra/test.rs @@ -26,12 +26,11 @@ use stats; use time::precise_time_ns; use collections::TreeMap; -use std::clone::Clone; use std::cmp; use std::io; -use std::io::File; -use std::io::Writer; +use std::io::{File, PortReader, ChanWriter}; use std::io::stdio::StdWriter; +use std::str; use std::task; use std::to_str::ToStr; use std::f64; @@ -358,7 +357,7 @@ struct ConsoleTestState { ignored: uint, measured: uint, metrics: MetricMap, - failures: ~[TestDesc], + failures: ~[(TestDesc, ~[u8])], max_name_len: uint, // number of columns to fill when aligning names } @@ -498,9 +497,23 @@ impl ConsoleTestState { pub fn write_failures(&mut self) -> io::IoResult<()> { if_ok!(self.write_plain("\nfailures:\n")); let mut failures = ~[]; - for f in self.failures.iter() { + let mut fail_out = ~""; + for &(ref f, ref stdout) in self.failures.iter() { failures.push(f.name.to_str()); + if stdout.len() > 0 { + fail_out.push_str(format!("---- {} stdout ----\n\t", + f.name.to_str())); + let output = str::from_utf8_lossy(*stdout); + fail_out.push_str(output.as_slice().replace("\n", "\n\t")); + fail_out.push_str("\n"); + } + } + if fail_out.len() > 0 { + if_ok!(self.write_plain("\n")); + if_ok!(self.write_plain(fail_out)); } + + if_ok!(self.write_plain("\nfailures:\n")); failures.sort(); for name in failures.iter() { if_ok!(self.write_plain(format!(" {}\n", name.to_str()))); @@ -632,7 +645,7 @@ pub fn run_tests_console(opts: &TestOpts, match (*event).clone() { TeFiltered(ref filtered_tests) => st.write_run_start(filtered_tests.len()), TeWait(ref test, padding) => st.write_test_start(test, padding), - TeResult(test, result) => { + TeResult(test, result, stdout) => { if_ok!(st.write_log(&test, &result)); if_ok!(st.write_result(&result)); match result { @@ -655,7 +668,7 @@ pub fn run_tests_console(opts: &TestOpts, } TrFailed => { st.failed += 1; - st.failures.push(test); + st.failures.push((test, stdout)); } } Ok(()) @@ -717,17 +730,17 @@ fn should_sort_failures_before_printing_them() { measured: 0u, max_name_len: 10u, metrics: MetricMap::new(), - failures: ~[test_b, test_a] + failures: ~[(test_b, ~[]), (test_a, ~[])] }; st.write_failures().unwrap(); let s = match st.out { - Raw(ref m) => str::from_utf8(m.get_ref()).unwrap(), + Raw(ref m) => str::from_utf8_lossy(m.get_ref()), Pretty(_) => unreachable!() }; - let apos = s.find_str("a").unwrap(); - let bpos = s.find_str("b").unwrap(); + let apos = s.as_slice().find_str("a").unwrap(); + let bpos = s.as_slice().find_str("b").unwrap(); assert!(apos < bpos); } @@ -737,11 +750,10 @@ fn use_color() -> bool { return get_concurrency() == 1; } enum TestEvent { TeFiltered(~[TestDesc]), TeWait(TestDesc, NamePadding), - TeResult(TestDesc, TestResult), + TeResult(TestDesc, TestResult, ~[u8] /* stdout */), } -/// The message sent to the test monitor from the individual runners. -pub type MonitorMsg = (TestDesc, TestResult); +pub type MonitorMsg = (TestDesc, TestResult, ~[u8] /* stdout */); fn run_tests(opts: &TestOpts, tests: ~[TestDescAndFn], @@ -783,11 +795,11 @@ fn run_tests(opts: &TestOpts, pending += 1; } - let (desc, result) = p.recv(); + let (desc, result, stdout) = p.recv(); if concurrency != 1 { if_ok!(callback(TeWait(desc.clone(), PadNone))); } - if_ok!(callback(TeResult(desc, result))); + if_ok!(callback(TeResult(desc, result, stdout))); pending -= 1; } @@ -796,8 +808,8 @@ fn run_tests(opts: &TestOpts, for b in filtered_benchs_and_metrics.move_iter() { if_ok!(callback(TeWait(b.desc.clone(), b.testfn.padding()))); run_test(!opts.run_benchmarks, b, ch.clone()); - let (test, result) = p.recv(); - if_ok!(callback(TeResult(test, result))); + let (test, result, stdout) = p.recv(); + if_ok!(callback(TeResult(test, result, stdout))); } Ok(()) } @@ -884,7 +896,7 @@ pub fn run_test(force_ignore: bool, let TestDescAndFn {desc, testfn} = test; if force_ignore || desc.ignore { - monitor_ch.send((desc, TrIgnored)); + monitor_ch.send((desc, TrIgnored, ~[])); return; } @@ -893,40 +905,47 @@ pub fn run_test(force_ignore: bool, testfn: proc()) { spawn(proc() { let mut task = task::task(); - task.name(match desc.name { - DynTestName(ref name) => name.to_owned().into_maybe_owned(), - StaticTestName(name) => name.into_maybe_owned() - }); + let (p, c) = Chan::new(); + let mut reader = PortReader::new(p); + let stdout = ChanWriter::new(c.clone()); + let stderr = ChanWriter::new(c); + match desc.name { + DynTestName(ref name) => task.name(name.clone()), + StaticTestName(name) => task.name(name), + } + task.opts.stdout = Some(~stdout as ~Writer); + task.opts.stderr = Some(~stderr as ~Writer); let result_future = task.future_result(); task.spawn(testfn); + let stdout = reader.read_to_end().unwrap(); let task_result = result_future.recv(); let test_result = calc_result(&desc, task_result.is_ok()); - monitor_ch.send((desc.clone(), test_result)); - }); + monitor_ch.send((desc.clone(), test_result, stdout)); + }) } match testfn { DynBenchFn(bencher) => { let bs = ::test::bench::benchmark(|harness| bencher.run(harness)); - monitor_ch.send((desc, TrBench(bs))); + monitor_ch.send((desc, TrBench(bs), ~[])); return; } StaticBenchFn(benchfn) => { let bs = ::test::bench::benchmark(|harness| benchfn(harness)); - monitor_ch.send((desc, TrBench(bs))); + monitor_ch.send((desc, TrBench(bs), ~[])); return; } DynMetricFn(f) => { let mut mm = MetricMap::new(); f(&mut mm); - monitor_ch.send((desc, TrMetrics(mm))); + monitor_ch.send((desc, TrMetrics(mm), ~[])); return; } StaticMetricFn(f) => { let mut mm = MetricMap::new(); f(&mut mm); - monitor_ch.send((desc, TrMetrics(mm))); + monitor_ch.send((desc, TrMetrics(mm), ~[])); return; } DynTestFn(f) => run_test_inner(desc, monitor_ch, f), @@ -1264,7 +1283,7 @@ mod tests { }; let (p, ch) = Chan::new(); run_test(false, desc, ch); - let (_, res) = p.recv(); + let (_, res, _) = p.recv(); assert!(res != TrOk); } @@ -1281,7 +1300,7 @@ mod tests { }; let (p, ch) = Chan::new(); run_test(false, desc, ch); - let (_, res) = p.recv(); + let (_, res, _) = p.recv(); assert_eq!(res, TrIgnored); } @@ -1298,7 +1317,7 @@ mod tests { }; let (p, ch) = Chan::new(); run_test(false, desc, ch); - let (_, res) = p.recv(); + let (_, res, _) = p.recv(); assert_eq!(res, TrOk); } @@ -1315,7 +1334,7 @@ mod tests { }; let (p, ch) = Chan::new(); run_test(false, desc, ch); - let (_, res) = p.recv(); + let (_, res, _) = p.recv(); assert_eq!(res, TrFailed); } diff --git a/src/libstd/io/comm_adapters.rs b/src/libstd/io/comm_adapters.rs index 6ed588ac69f..bf2c6dbb623 100644 --- a/src/libstd/io/comm_adapters.rs +++ b/src/libstd/io/comm_adapters.rs @@ -96,6 +96,12 @@ impl ChanWriter { } } +impl Clone for ChanWriter { + fn clone(&self) -> ChanWriter { + ChanWriter { chan: self.chan.clone() } + } +} + impl Writer for ChanWriter { fn write(&mut self, buf: &[u8]) -> IoResult<()> { if !self.chan.try_send(buf.to_owned()) { diff --git a/src/test/run-fail/run-unexported-tests.rs b/src/test/run-fail/run-unexported-tests.rs index e9d3c41faa6..427e606147d 100644 --- a/src/test/run-fail/run-unexported-tests.rs +++ b/src/test/run-fail/run-unexported-tests.rs @@ -10,6 +10,7 @@ // error-pattern:runned an unexported test // compile-flags:--test +// check-stdout extern mod extra; diff --git a/src/test/run-fail/test-fail.rs b/src/test/run-fail/test-fail.rs index ddd54f00159..77d87c22c6f 100644 --- a/src/test/run-fail/test-fail.rs +++ b/src/test/run-fail/test-fail.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// check-stdout // error-pattern:task 'test_foo' failed at // compile-flags: --test -- cgit 1.4.1-3-g733a5