diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2012-01-03 21:01:48 -0800 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2012-01-04 15:25:17 -0800 |
| commit | 70c808d173cfb7315131e6bf75e36fa4c9ee7db1 (patch) | |
| tree | 6555fe35e63ca00b2e3e91a1c5a025095f2c540d /src/compiletest | |
| parent | 3971b520bcdd556ff78120c77ffd13785e1c3695 (diff) | |
| download | rust-70c808d173cfb7315131e6bf75e36fa4c9ee7db1.tar.gz rust-70c808d173cfb7315131e6bf75e36fa4c9ee7db1.zip | |
extend tester so that error msgs can be attached to lines
Diffstat (limited to 'src/compiletest')
| -rw-r--r-- | src/compiletest/compiletest.rc | 2 | ||||
| -rw-r--r-- | src/compiletest/errors.rs | 54 | ||||
| -rw-r--r-- | src/compiletest/runtest.rs | 69 |
3 files changed, 122 insertions, 3 deletions
diff --git a/src/compiletest/compiletest.rc b/src/compiletest/compiletest.rc index 703862076a5..a0deaeda26a 100644 --- a/src/compiletest/compiletest.rc +++ b/src/compiletest/compiletest.rc @@ -5,11 +5,11 @@ mod util; mod header; mod runtest; mod common; +mod errors; // Local Variables: // fill-column: 78; // indent-tabs-mode: nil // c-basic-offset: 4 // buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; // End: diff --git a/src/compiletest/errors.rs b/src/compiletest/errors.rs new file mode 100644 index 00000000000..c0d96fc5142 --- /dev/null +++ b/src/compiletest/errors.rs @@ -0,0 +1,54 @@ +import option; +import str; +import std::io; +import std::fs; + +import common::config; + +export load_errors; +export expected_error; + +type expected_error = { line: uint, kind: str, msg: str }; + +// Load any test directives embedded in the file +fn load_errors(testfile: str) -> [expected_error] { + let error_patterns = []; + let rdr = result::get(io::file_reader(testfile)); + let line_num = 1u; + while !rdr.eof() { + let ln = rdr.read_line(); + error_patterns += parse_expected(line_num, ln); + line_num += 1u; + } + ret error_patterns; +} + +fn parse_expected(line_num: uint, line: str) -> [expected_error] { + let error_tag = "//!"; + let idx0 = str::find(line, error_tag); + if idx0 < 0 { ret []; } + let idx = (idx0 as uint) + str::byte_len(error_tag); + + // "//!^^^ kind msg" denotes a message expected + // three lines above current line: + let adjust_line = 0u; + let len = str::byte_len(line); + while idx < len && line[idx] == ('^' as u8) { + adjust_line += 1u; + idx += 1u; + } + + // Extract kind: + while idx < len && line[idx] == (' ' as u8) { idx += 1u; } + let start_kind = idx; + while idx < len && line[idx] != (' ' as u8) { idx += 1u; } + let kind = str::to_lower(str::slice(line, start_kind, idx)); + + // Extract msg: + while idx < len && line[idx] == (' ' as u8) { idx += 1u; } + let msg = str::slice(line, idx, len); + + #debug("line=%u kind=%s msg=%s", line_num - adjust_line, kind, msg); + + ret [{line: line_num - adjust_line, kind: kind, msg: msg}]; +} diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index fefa9d7e617..3fc5fc4c75e 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -42,7 +42,16 @@ fn run_cfail_test(cx: cx, props: test_props, testfile: str) { } check_correct_failure_status(procres); - check_error_patterns(props, testfile, procres); + + let expected_errors = errors::load_errors(testfile); + if vec::is_not_empty(expected_errors) { + if vec::is_not_empty(props.error_patterns) { + fatal("both error pattern and expected errors specified"); + } + check_expected_errors(expected_errors, testfile, procres); + } else { + check_error_patterns(props, testfile, procres); + } } fn run_rfail_test(cx: cx, props: test_props, testfile: str) { @@ -181,7 +190,9 @@ actual:\n\ } } -fn check_error_patterns(props: test_props, testfile: str, procres: procres) { +fn check_error_patterns(props: test_props, + testfile: str, + procres: procres) { if vec::is_empty(props.error_patterns) { fatal("no error pattern specified in " + testfile); } @@ -218,6 +229,60 @@ fn check_error_patterns(props: test_props, testfile: str, procres: procres) { } } +fn check_expected_errors(expected_errors: [errors::expected_error], + testfile: str, + procres: procres) { + + // true if we found the error in question + let found_flags = vec::init_elt_mut(false, vec::len(expected_errors)); + + if procres.status == 0 { + fatal("process did not return an error status"); + } + + // Scan and extract our error/warning messages, + // which look like: + // filename:line1:col1: line2:col2: *error:* msg + // filename:line1:col1: line2:col2: *warning:* msg + // where line1:col1: is the starting point, line2:col2: + // is the ending point, and * represents ANSI color codes. + for line: str in str::split(procres.stdout, '\n' as u8) { + let was_expected = false; + vec::iteri(expected_errors) {|i, ee| + if !found_flags[i] { + let needle = #fmt("%s:%u:", testfile, ee.line); + #debug["needle=%s ee.kind=%s ee.msg=%s line=%s", + needle, ee.kind, ee.msg, line]; + if (str::contains(line, needle) && + str::contains(line, ee.kind) && + str::contains(line, ee.msg)) { + found_flags[i] = true; + was_expected = true; + } + } + } + + // ignore this msg which gets printed at the end + if str::contains(line, "aborting due to previous errors") { + was_expected = true; + } + + if !was_expected && (str::contains(line, "error") || + str::contains(line, "warning")) { + fatal_procres(#fmt["unexpected error pattern '%s'!", line], + procres); + } + } + + uint::range(0u, vec::len(found_flags)) {|i| + if !found_flags[i] { + let ee = expected_errors[i]; + fatal_procres(#fmt["expected %s on line %u not found: %s", + ee.kind, ee.line, ee.msg], procres); + } + } +} + type procargs = {prog: str, args: [str]}; type procres = {status: int, stdout: str, stderr: str, cmdline: str}; |
