2012-01-11 08:15:54 -06:00
|
|
|
import io::writer_util;
|
2011-07-30 23:11:14 -05:00
|
|
|
|
|
|
|
import common::mode_run_pass;
|
|
|
|
import common::mode_run_fail;
|
|
|
|
import common::mode_compile_fail;
|
2011-07-30 23:44:30 -05:00
|
|
|
import common::mode_pretty;
|
2011-07-30 23:11:14 -05:00
|
|
|
import common::config;
|
|
|
|
import header::load_props;
|
|
|
|
import header::test_props;
|
|
|
|
import util::logv;
|
|
|
|
|
|
|
|
export run;
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
fn run(config: config, testfile: ~str) {
|
2012-02-07 20:55:02 -06:00
|
|
|
if config.verbose {
|
2011-07-30 23:11:14 -05:00
|
|
|
// We're going to be dumping a lot of info. Start on a new line.
|
2012-07-14 00:57:48 -05:00
|
|
|
io::stdout().write_str(~"\n\n");
|
2011-07-30 23:11:14 -05:00
|
|
|
}
|
2012-07-30 18:01:07 -05:00
|
|
|
debug!{"running %s", testfile};
|
2011-07-30 23:11:14 -05:00
|
|
|
let props = load_props(testfile);
|
2012-02-07 20:55:02 -06:00
|
|
|
alt config.mode {
|
2012-08-03 21:59:04 -05:00
|
|
|
mode_compile_fail => run_cfail_test(config, props, testfile),
|
|
|
|
mode_run_fail => run_rfail_test(config, props, testfile),
|
|
|
|
mode_run_pass => run_rpass_test(config, props, testfile),
|
|
|
|
mode_pretty => run_pretty_test(config, props, testfile)
|
2011-07-30 23:11:14 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
fn run_cfail_test(config: config, props: test_props, testfile: ~str) {
|
2012-02-07 20:55:02 -06:00
|
|
|
let procres = compile_test(config, props, testfile);
|
2011-07-30 23:11:14 -05:00
|
|
|
|
|
|
|
if procres.status == 0 {
|
2012-07-14 00:57:48 -05:00
|
|
|
fatal_procres(~"compile-fail test compiled successfully!", procres);
|
2011-07-30 23:11:14 -05:00
|
|
|
}
|
|
|
|
|
2011-09-16 13:44:55 -05:00
|
|
|
check_correct_failure_status(procres);
|
2012-01-03 23:01:48 -06:00
|
|
|
|
|
|
|
let expected_errors = errors::load_errors(testfile);
|
|
|
|
if vec::is_not_empty(expected_errors) {
|
|
|
|
if vec::is_not_empty(props.error_patterns) {
|
2012-07-14 00:57:48 -05:00
|
|
|
fatal(~"both error pattern and expected errors specified");
|
2012-01-03 23:01:48 -06:00
|
|
|
}
|
|
|
|
check_expected_errors(expected_errors, testfile, procres);
|
|
|
|
} else {
|
|
|
|
check_error_patterns(props, testfile, procres);
|
|
|
|
}
|
2011-07-30 23:11:14 -05:00
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
fn run_rfail_test(config: config, props: test_props, testfile: ~str) {
|
2012-03-22 10:39:41 -05:00
|
|
|
let mut procres = compile_test(config, props, testfile);
|
2011-07-30 23:11:14 -05:00
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
if procres.status != 0 { fatal_procres(~"compilation failed!", procres); }
|
2011-07-30 23:11:14 -05:00
|
|
|
|
2012-02-07 20:55:02 -06:00
|
|
|
procres = exec_compiled_test(config, props, testfile);
|
2011-07-30 23:11:14 -05:00
|
|
|
|
2011-09-08 15:42:04 -05:00
|
|
|
// The value our Makefile configures valgrind to return on failure
|
2011-09-08 15:28:03 -05:00
|
|
|
const valgrind_err: int = 100;
|
2011-08-10 15:36:57 -05:00
|
|
|
if procres.status == valgrind_err {
|
2012-07-14 00:57:48 -05:00
|
|
|
fatal_procres(~"run-fail test isn't valgrind-clean!", procres);
|
2011-08-10 15:36:57 -05:00
|
|
|
}
|
|
|
|
|
2011-09-16 13:44:55 -05:00
|
|
|
check_correct_failure_status(procres);
|
|
|
|
check_error_patterns(props, testfile, procres);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn check_correct_failure_status(procres: procres) {
|
2011-09-08 15:42:04 -05:00
|
|
|
// The value the rust runtime returns on failure
|
|
|
|
const rust_err: int = 101;
|
|
|
|
if procres.status != rust_err {
|
|
|
|
fatal_procres(
|
2012-07-30 18:01:07 -05:00
|
|
|
fmt!{"failure produced the wrong error code: %d",
|
|
|
|
procres.status},
|
2011-09-08 15:42:04 -05:00
|
|
|
procres);
|
|
|
|
}
|
2011-07-30 23:11:14 -05:00
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
fn run_rpass_test(config: config, props: test_props, testfile: ~str) {
|
2012-03-22 10:39:41 -05:00
|
|
|
let mut procres = compile_test(config, props, testfile);
|
2011-07-30 23:11:14 -05:00
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
if procres.status != 0 { fatal_procres(~"compilation failed!", procres); }
|
2011-07-30 23:11:14 -05:00
|
|
|
|
2012-02-07 20:55:02 -06:00
|
|
|
procres = exec_compiled_test(config, props, testfile);
|
2011-07-30 23:11:14 -05:00
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
if procres.status != 0 { fatal_procres(~"test run failed!", procres); }
|
2011-07-30 23:11:14 -05:00
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
fn run_pretty_test(config: config, props: test_props, testfile: ~str) {
|
2011-08-01 16:10:59 -05:00
|
|
|
if option::is_some(props.pp_exact) {
|
2012-07-14 00:57:48 -05:00
|
|
|
logv(config, ~"testing for exact pretty-printing");
|
|
|
|
} else { logv(config, ~"testing for converging pretty-printing"); }
|
2011-08-01 16:10:59 -05:00
|
|
|
|
2011-08-19 17:16:48 -05:00
|
|
|
let rounds =
|
2012-08-03 21:59:04 -05:00
|
|
|
alt props.pp_exact { option::some(_) => 1, option::none => 2 };
|
2011-07-31 17:33:40 -05:00
|
|
|
|
2012-06-29 18:26:56 -05:00
|
|
|
let mut srcs = ~[result::get(io::read_whole_file_str(testfile))];
|
2011-07-31 17:33:40 -05:00
|
|
|
|
2012-03-22 10:39:41 -05:00
|
|
|
let mut round = 0;
|
2011-07-31 17:33:40 -05:00
|
|
|
while round < rounds {
|
2012-07-30 18:01:07 -05:00
|
|
|
logv(config, fmt!{"pretty-printing round %d", round});
|
2012-02-07 20:55:02 -06:00
|
|
|
let procres = print_source(config, testfile, srcs[round]);
|
2011-07-31 17:33:40 -05:00
|
|
|
|
|
|
|
if procres.status != 0 {
|
2012-07-30 18:01:07 -05:00
|
|
|
fatal_procres(fmt!{"pretty-printing failed in round %d", round},
|
2011-09-02 17:34:58 -05:00
|
|
|
procres);
|
2011-07-31 17:33:40 -05:00
|
|
|
}
|
|
|
|
|
2012-06-15 20:16:42 -05:00
|
|
|
vec::push(srcs, procres.stdout);
|
2011-07-31 17:33:40 -05:00
|
|
|
round += 1;
|
|
|
|
}
|
|
|
|
|
2012-03-22 10:39:41 -05:00
|
|
|
let mut expected =
|
2011-08-19 17:16:48 -05:00
|
|
|
alt props.pp_exact {
|
2012-08-03 21:59:04 -05:00
|
|
|
option::some(file) => {
|
2012-03-12 22:04:27 -05:00
|
|
|
let filepath = path::connect(path::dirname(testfile), file);
|
2011-10-28 23:19:59 -05:00
|
|
|
result::get(io::read_whole_file_str(filepath))
|
2011-08-19 17:16:48 -05:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
option::none => { srcs[vec::len(srcs) - 2u] }
|
2011-08-19 17:16:48 -05:00
|
|
|
};
|
2012-03-22 10:39:41 -05:00
|
|
|
let mut actual = srcs[vec::len(srcs) - 1u];
|
2011-08-03 18:25:38 -05:00
|
|
|
|
2011-08-03 17:36:45 -05:00
|
|
|
if option::is_some(props.pp_exact) {
|
|
|
|
// Now we have to care about line endings
|
2012-07-14 00:57:48 -05:00
|
|
|
let cr = ~"\r";
|
|
|
|
actual = str::replace(actual, cr, ~"");
|
|
|
|
expected = str::replace(expected, cr, ~"");
|
2011-08-03 17:36:45 -05:00
|
|
|
}
|
2011-07-31 17:33:40 -05:00
|
|
|
|
|
|
|
compare_source(expected, actual);
|
|
|
|
|
|
|
|
// Finally, let's make sure it actually appears to remain valid code
|
2012-03-28 16:58:31 -05:00
|
|
|
let procres = typecheck_source(config, props, testfile, actual);
|
2011-07-31 17:33:40 -05:00
|
|
|
|
|
|
|
if procres.status != 0 {
|
2012-07-14 00:57:48 -05:00
|
|
|
fatal_procres(~"pretty-printed source does not typecheck", procres);
|
2011-07-31 17:33:40 -05:00
|
|
|
}
|
|
|
|
|
2012-08-01 19:30:05 -05:00
|
|
|
return;
|
2011-07-31 17:33:40 -05:00
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
fn print_source(config: config, testfile: ~str, src: ~str) -> procres {
|
2012-04-13 11:19:07 -05:00
|
|
|
compose_and_run(config, testfile, make_pp_args(config, testfile),
|
2012-06-29 18:26:56 -05:00
|
|
|
~[], config.compile_lib_path, option::some(src))
|
2011-07-31 17:33:40 -05:00
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
fn make_pp_args(config: config, _testfile: ~str) -> procargs {
|
2011-08-30 17:40:25 -05:00
|
|
|
let prog = config.rustc_path;
|
2012-07-14 00:57:48 -05:00
|
|
|
let args = ~[~"-", ~"--pretty", ~"normal"];
|
2012-08-01 19:30:05 -05:00
|
|
|
return {prog: prog, args: args};
|
2011-07-31 17:33:40 -05:00
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
fn compare_source(expected: ~str, actual: ~str) {
|
2011-07-31 17:33:40 -05:00
|
|
|
if expected != actual {
|
2012-07-14 00:57:48 -05:00
|
|
|
error(~"pretty-printed source does not match expected source");
|
2011-08-19 17:16:48 -05:00
|
|
|
let msg =
|
2012-07-30 18:01:07 -05:00
|
|
|
fmt!{"\n\
|
2011-07-31 17:33:40 -05:00
|
|
|
expected:\n\
|
|
|
|
------------------------------------------\n\
|
|
|
|
%s\n\
|
|
|
|
------------------------------------------\n\
|
|
|
|
actual:\n\
|
|
|
|
------------------------------------------\n\
|
|
|
|
%s\n\
|
|
|
|
------------------------------------------\n\
|
|
|
|
\n",
|
2012-07-30 18:01:07 -05:00
|
|
|
expected, actual};
|
2011-08-28 02:24:28 -05:00
|
|
|
io::stdout().write_str(msg);
|
2011-07-31 17:33:40 -05:00
|
|
|
fail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-28 16:58:31 -05:00
|
|
|
fn typecheck_source(config: config, props: test_props,
|
2012-07-14 00:57:48 -05:00
|
|
|
testfile: ~str, src: ~str) -> procres {
|
2012-03-28 16:58:31 -05:00
|
|
|
compose_and_run_compiler(
|
2012-04-13 11:19:07 -05:00
|
|
|
config, props, testfile,
|
|
|
|
make_typecheck_args(config, testfile),
|
|
|
|
option::some(src))
|
2011-07-31 21:12:33 -05:00
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
fn make_typecheck_args(config: config, testfile: ~str) -> procargs {
|
2011-08-30 17:40:25 -05:00
|
|
|
let prog = config.rustc_path;
|
2012-07-14 00:57:48 -05:00
|
|
|
let mut args = ~[~"-",
|
|
|
|
~"--no-trans", ~"--lib", ~"-L", config.build_base,
|
|
|
|
~"-L", aux_output_dir_name(config, testfile)];
|
2011-11-23 18:18:32 -06:00
|
|
|
args += split_maybe_args(config.rustcflags);
|
2012-08-01 19:30:05 -05:00
|
|
|
return {prog: prog, args: args};
|
2011-07-31 17:33:40 -05:00
|
|
|
}
|
2011-07-30 23:44:30 -05:00
|
|
|
}
|
|
|
|
|
2012-01-03 23:01:48 -06:00
|
|
|
fn check_error_patterns(props: test_props,
|
2012-07-14 00:57:48 -05:00
|
|
|
testfile: ~str,
|
2012-01-03 23:01:48 -06:00
|
|
|
procres: procres) {
|
2011-08-15 18:38:23 -05:00
|
|
|
if vec::is_empty(props.error_patterns) {
|
2012-07-14 00:57:48 -05:00
|
|
|
fatal(~"no error pattern specified in " + testfile);
|
2011-07-30 23:11:14 -05:00
|
|
|
}
|
|
|
|
|
2011-08-24 15:24:03 -05:00
|
|
|
if procres.status == 0 {
|
2012-07-14 00:57:48 -05:00
|
|
|
fatal(~"process did not return an error status");
|
2011-08-24 15:24:03 -05:00
|
|
|
}
|
|
|
|
|
2012-03-22 10:39:41 -05:00
|
|
|
let mut next_err_idx = 0u;
|
|
|
|
let mut next_err_pat = props.error_patterns[next_err_idx];
|
2012-04-06 13:36:43 -05:00
|
|
|
let mut done = false;
|
2012-06-30 18:19:07 -05:00
|
|
|
for str::split_char(procres.stderr, '\n').each |line| {
|
2012-02-13 00:00:56 -06:00
|
|
|
if str::contains(line, next_err_pat) {
|
2012-07-30 18:01:07 -05:00
|
|
|
debug!{"found error pattern %s", next_err_pat};
|
2011-07-30 23:11:14 -05:00
|
|
|
next_err_idx += 1u;
|
2011-08-15 18:38:23 -05:00
|
|
|
if next_err_idx == vec::len(props.error_patterns) {
|
2012-07-30 18:01:07 -05:00
|
|
|
debug!{"found all error patterns"};
|
2012-04-06 13:36:43 -05:00
|
|
|
done = true;
|
|
|
|
break;
|
2011-07-30 23:11:14 -05:00
|
|
|
}
|
2011-08-19 17:16:48 -05:00
|
|
|
next_err_pat = props.error_patterns[next_err_idx];
|
2011-07-30 23:11:14 -05:00
|
|
|
}
|
|
|
|
}
|
2012-08-01 19:30:05 -05:00
|
|
|
if done { return; }
|
2011-07-30 23:11:14 -05:00
|
|
|
|
|
|
|
let missing_patterns =
|
2011-08-15 18:38:23 -05:00
|
|
|
vec::slice(props.error_patterns, next_err_idx,
|
2011-08-19 17:16:48 -05:00
|
|
|
vec::len(props.error_patterns));
|
2011-08-15 18:38:23 -05:00
|
|
|
if vec::len(missing_patterns) == 1u {
|
2012-07-30 18:01:07 -05:00
|
|
|
fatal_procres(fmt!{"error pattern '%s' not found!",
|
|
|
|
missing_patterns[0]}, procres);
|
2011-07-30 23:11:14 -05:00
|
|
|
} else {
|
2012-06-30 18:19:07 -05:00
|
|
|
for missing_patterns.each |pattern| {
|
2012-07-30 18:01:07 -05:00
|
|
|
error(fmt!{"error pattern '%s' not found!", pattern});
|
2011-07-30 23:11:14 -05:00
|
|
|
}
|
2012-07-14 00:57:48 -05:00
|
|
|
fatal_procres(~"multiple error patterns not found", procres);
|
2011-07-30 23:11:14 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-29 18:26:56 -05:00
|
|
|
fn check_expected_errors(expected_errors: ~[errors::expected_error],
|
2012-07-14 00:57:48 -05:00
|
|
|
testfile: ~str,
|
2012-01-03 23:01:48 -06:00
|
|
|
procres: procres) {
|
|
|
|
|
|
|
|
// true if we found the error in question
|
2012-03-12 17:52:30 -05:00
|
|
|
let found_flags = vec::to_mut(vec::from_elem(
|
2012-03-01 01:44:52 -06:00
|
|
|
vec::len(expected_errors), false));
|
2012-01-03 23:01:48 -06:00
|
|
|
|
|
|
|
if procres.status == 0 {
|
2012-07-14 00:57:48 -05:00
|
|
|
fatal(~"process did not return an error status");
|
2012-01-03 23:01:48 -06:00
|
|
|
}
|
|
|
|
|
2012-06-30 18:19:07 -05:00
|
|
|
let prefixes = vec::map(expected_errors, |ee| {
|
2012-07-30 18:01:07 -05:00
|
|
|
fmt!{"%s:%u:", testfile, ee.line}
|
2012-01-03 23:26:31 -06:00
|
|
|
});
|
|
|
|
|
2012-01-03 23:01:48 -06:00
|
|
|
// 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.
|
2012-06-30 18:19:07 -05:00
|
|
|
for str::split_char(procres.stderr, '\n').each |line| {
|
2012-03-22 10:39:41 -05:00
|
|
|
let mut was_expected = false;
|
2012-06-30 18:19:07 -05:00
|
|
|
for vec::eachi(expected_errors) |i, ee| {
|
2012-01-03 23:01:48 -06:00
|
|
|
if !found_flags[i] {
|
2012-07-30 18:01:07 -05:00
|
|
|
debug!{"prefix=%s ee.kind=%s ee.msg=%s line=%s",
|
|
|
|
prefixes[i], ee.kind, ee.msg, line};
|
2012-01-03 23:26:31 -06:00
|
|
|
if (str::starts_with(line, prefixes[i]) &&
|
2012-01-03 23:01:48 -06:00
|
|
|
str::contains(line, ee.kind) &&
|
|
|
|
str::contains(line, ee.msg)) {
|
|
|
|
found_flags[i] = true;
|
|
|
|
was_expected = true;
|
2012-04-05 22:58:23 -05:00
|
|
|
break;
|
2012-01-03 23:01:48 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ignore this msg which gets printed at the end
|
2012-07-14 00:57:48 -05:00
|
|
|
if str::contains(line, ~"aborting due to") {
|
2012-01-03 23:01:48 -06:00
|
|
|
was_expected = true;
|
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
if !was_expected && (str::contains(line, ~"error") ||
|
|
|
|
str::contains(line, ~"warning")) {
|
2012-07-30 18:01:07 -05:00
|
|
|
fatal_procres(fmt!{"unexpected error pattern '%s'!", line},
|
2012-01-03 23:01:48 -06:00
|
|
|
procres);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-30 18:19:07 -05:00
|
|
|
for uint::range(0u, vec::len(found_flags)) |i| {
|
2012-01-03 23:01:48 -06:00
|
|
|
if !found_flags[i] {
|
|
|
|
let ee = expected_errors[i];
|
2012-07-30 18:01:07 -05:00
|
|
|
fatal_procres(fmt!{"expected %s on line %u not found: %s",
|
|
|
|
ee.kind, ee.line, ee.msg}, procres);
|
2012-01-03 23:01:48 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
type procargs = {prog: ~str, args: ~[~str]};
|
2011-07-30 23:11:14 -05:00
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
type procres = {status: int, stdout: ~str, stderr: ~str, cmdline: ~str};
|
2011-07-30 23:11:14 -05:00
|
|
|
|
2012-02-07 20:55:02 -06:00
|
|
|
fn compile_test(config: config, props: test_props,
|
2012-07-14 00:57:48 -05:00
|
|
|
testfile: ~str) -> procres {
|
|
|
|
let link_args = ~[~"-L", aux_output_dir_name(config, testfile)];
|
2012-04-13 11:19:07 -05:00
|
|
|
compose_and_run_compiler(
|
|
|
|
config, props, testfile,
|
|
|
|
make_compile_args(config, props, link_args,
|
|
|
|
make_exe_name, testfile),
|
|
|
|
none)
|
2012-03-28 16:58:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn exec_compiled_test(config: config, props: test_props,
|
2012-07-14 00:57:48 -05:00
|
|
|
testfile: ~str) -> procres {
|
2012-03-28 16:58:31 -05:00
|
|
|
compose_and_run(config, testfile,
|
2012-04-13 11:19:07 -05:00
|
|
|
make_run_args(config, props, testfile),
|
|
|
|
props.exec_env,
|
|
|
|
config.run_lib_path, option::none)
|
2012-03-28 16:58:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn compose_and_run_compiler(
|
|
|
|
config: config,
|
|
|
|
props: test_props,
|
2012-07-14 00:57:48 -05:00
|
|
|
testfile: ~str,
|
2012-04-13 11:19:07 -05:00
|
|
|
args: procargs,
|
2012-07-14 00:57:48 -05:00
|
|
|
input: option<~str>) -> procres {
|
2012-03-28 16:58:31 -05:00
|
|
|
|
2012-04-10 00:41:27 -05:00
|
|
|
if props.aux_builds.is_not_empty() {
|
|
|
|
ensure_dir(aux_output_dir_name(config, testfile));
|
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
let extra_link_args = ~[~"-L", aux_output_dir_name(config, testfile)];
|
2012-04-10 00:41:27 -05:00
|
|
|
|
2012-06-30 18:19:07 -05:00
|
|
|
do vec::iter(props.aux_builds) |rel_ab| {
|
2012-03-12 22:04:27 -05:00
|
|
|
let abs_ab = path::connect(config.aux_base, rel_ab);
|
2012-04-13 11:19:07 -05:00
|
|
|
let aux_args =
|
2012-07-14 00:57:48 -05:00
|
|
|
make_compile_args(config, props, ~[~"--lib"] + extra_link_args,
|
2012-06-30 18:19:07 -05:00
|
|
|
|a,b| make_lib_name(a, b, testfile), abs_ab);
|
2012-06-29 18:26:56 -05:00
|
|
|
let auxres = compose_and_run(config, abs_ab, aux_args, ~[],
|
2012-03-01 12:36:22 -06:00
|
|
|
config.compile_lib_path, option::none);
|
|
|
|
if auxres.status != 0 {
|
|
|
|
fatal_procres(
|
2012-07-30 18:01:07 -05:00
|
|
|
fmt!{"auxiliary build of %s failed to compile: ", abs_ab},
|
2012-03-01 12:36:22 -06:00
|
|
|
auxres);
|
|
|
|
}
|
2012-02-27 23:23:49 -06:00
|
|
|
}
|
|
|
|
|
2012-06-29 18:26:56 -05:00
|
|
|
compose_and_run(config, testfile, args, ~[],
|
2012-03-28 16:58:31 -05:00
|
|
|
config.compile_lib_path, input)
|
2011-07-30 23:11:14 -05:00
|
|
|
}
|
|
|
|
|
2012-04-10 00:41:27 -05:00
|
|
|
fn ensure_dir(path: path) {
|
2012-08-01 19:30:05 -05:00
|
|
|
if os::path_is_dir(path) { return; }
|
2012-04-10 00:41:27 -05:00
|
|
|
if !os::make_dir(path, 0x1c0i32) {
|
2012-07-30 18:01:07 -05:00
|
|
|
fail fmt!{"can't make dir %s", path};
|
2012-04-10 00:41:27 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
fn compose_and_run(config: config, testfile: ~str,
|
2012-04-13 11:19:07 -05:00
|
|
|
procargs: procargs,
|
2012-07-14 00:57:48 -05:00
|
|
|
procenv: ~[(~str, ~str)],
|
|
|
|
lib_path: ~str,
|
|
|
|
input: option<~str>) -> procres {
|
2012-08-01 19:30:05 -05:00
|
|
|
return program_output(config, testfile, lib_path,
|
2012-04-13 11:19:07 -05:00
|
|
|
procargs.prog, procargs.args, procenv, input);
|
2011-07-30 23:11:14 -05:00
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
fn make_compile_args(config: config, props: test_props, extras: ~[~str],
|
|
|
|
xform: fn(config, ~str) -> ~str, testfile: ~str) ->
|
2011-08-19 17:16:48 -05:00
|
|
|
procargs {
|
2011-08-30 17:40:25 -05:00
|
|
|
let prog = config.rustc_path;
|
2012-07-14 00:57:48 -05:00
|
|
|
let mut args = ~[testfile, ~"-o", xform(config, testfile),
|
|
|
|
~"-L", config.build_base] + extras;
|
2011-11-23 18:18:32 -06:00
|
|
|
args += split_maybe_args(config.rustcflags);
|
2011-07-30 23:11:14 -05:00
|
|
|
args += split_maybe_args(props.compile_flags);
|
2012-08-01 19:30:05 -05:00
|
|
|
return {prog: prog, args: args};
|
2011-07-30 23:11:14 -05:00
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
fn make_lib_name(config: config, auxfile: ~str, testfile: ~str) -> ~str {
|
2012-02-27 23:23:49 -06:00
|
|
|
// what we return here is not particularly important, as it
|
|
|
|
// happens; rustc ignores everything except for the directory.
|
2012-04-10 00:41:27 -05:00
|
|
|
let auxname = output_testname(auxfile);
|
|
|
|
path::connect(aux_output_dir_name(config, testfile), auxname)
|
2012-02-27 23:23:49 -06:00
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
fn make_exe_name(config: config, testfile: ~str) -> ~str {
|
2012-03-12 22:04:27 -05:00
|
|
|
output_base_name(config, testfile) + os::exe_suffix()
|
2011-07-30 23:11:14 -05:00
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
fn make_run_args(config: config, _props: test_props, testfile: ~str) ->
|
2011-08-19 17:16:48 -05:00
|
|
|
procargs {
|
2011-09-07 19:16:04 -05:00
|
|
|
let toolargs = {
|
2011-09-02 17:34:58 -05:00
|
|
|
// If we've got another tool to run under (valgrind),
|
|
|
|
// then split apart its command
|
|
|
|
let runtool =
|
|
|
|
alt config.runtool {
|
2012-08-03 21:59:04 -05:00
|
|
|
option::some(s) => option::some(s),
|
|
|
|
option::none => option::none
|
2011-09-02 17:34:58 -05:00
|
|
|
};
|
|
|
|
split_maybe_args(runtool)
|
2011-09-07 19:16:04 -05:00
|
|
|
};
|
2011-08-19 17:16:48 -05:00
|
|
|
|
2012-06-29 18:26:56 -05:00
|
|
|
let args = toolargs + ~[make_exe_name(config, testfile)];
|
2012-08-01 19:30:05 -05:00
|
|
|
return {prog: args[0], args: vec::slice(args, 1u, vec::len(args))};
|
2011-07-30 23:11:14 -05:00
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
fn split_maybe_args(argstr: option<~str>) -> ~[~str] {
|
|
|
|
fn rm_whitespace(v: ~[~str]) -> ~[~str] {
|
|
|
|
fn flt(&&s: ~str) -> option<~str> {
|
2012-03-15 17:28:33 -05:00
|
|
|
if !str::is_whitespace(s) { option::some(s) } else { option::none }
|
2011-07-30 23:11:14 -05:00
|
|
|
}
|
2011-12-16 08:27:50 -06:00
|
|
|
vec::filter_map(v, flt)
|
2011-07-30 23:11:14 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
alt argstr {
|
2012-08-03 21:59:04 -05:00
|
|
|
option::some(s) => rm_whitespace(str::split_char(s, ' ')),
|
|
|
|
option::none => ~[]
|
2011-07-30 23:11:14 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
fn program_output(config: config, testfile: ~str, lib_path: ~str, prog: ~str,
|
|
|
|
args: ~[~str], env: ~[(~str, ~str)],
|
|
|
|
input: option<~str>) -> procres {
|
2011-07-30 23:11:14 -05:00
|
|
|
let cmdline =
|
2011-08-19 17:16:48 -05:00
|
|
|
{
|
|
|
|
let cmdline = make_cmdline(lib_path, prog, args);
|
2012-07-30 18:01:07 -05:00
|
|
|
logv(config, fmt!{"executing %s", cmdline});
|
2011-08-19 17:16:48 -05:00
|
|
|
cmdline
|
|
|
|
};
|
2012-04-13 11:19:07 -05:00
|
|
|
let res = procsrv::run(lib_path, prog, args, env, input);
|
2012-02-07 20:55:02 -06:00
|
|
|
dump_output(config, testfile, res.out, res.err);
|
2012-08-01 19:30:05 -05:00
|
|
|
return {status: res.status,
|
2011-08-19 17:16:48 -05:00
|
|
|
stdout: res.out,
|
|
|
|
stderr: res.err,
|
|
|
|
cmdline: cmdline};
|
2011-07-30 23:11:14 -05:00
|
|
|
}
|
|
|
|
|
2011-10-09 17:23:41 -05:00
|
|
|
// Linux and mac don't require adjusting the library search path
|
|
|
|
#[cfg(target_os = "linux")]
|
|
|
|
#[cfg(target_os = "macos")]
|
2011-12-30 02:18:55 -06:00
|
|
|
#[cfg(target_os = "freebsd")]
|
2012-07-14 00:57:48 -05:00
|
|
|
fn make_cmdline(_libpath: ~str, prog: ~str, args: ~[~str]) -> ~str {
|
2012-07-30 18:01:07 -05:00
|
|
|
fmt!{"%s %s", prog, str::connect(args, ~" ")}
|
2011-10-09 17:23:41 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_os = "win32")]
|
2012-07-14 20:28:20 -05:00
|
|
|
fn make_cmdline(libpath: ~str, prog: ~str, args: ~[~str]) -> ~str {
|
2012-07-30 18:01:07 -05:00
|
|
|
fmt!{"%s %s %s", lib_path_cmd_prefix(libpath), prog,
|
|
|
|
str::connect(args, ~" ")}
|
2011-07-30 23:11:14 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Build the LD_LIBRARY_PATH variable as it would be seen on the command line
|
|
|
|
// for diagnostic purposes
|
2012-07-14 00:57:48 -05:00
|
|
|
fn lib_path_cmd_prefix(path: ~str) -> ~str {
|
2012-07-30 18:01:07 -05:00
|
|
|
fmt!{"%s=\"%s\"", util::lib_path_env_var(), util::make_new_path(path)}
|
2011-07-30 23:11:14 -05:00
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
fn dump_output(config: config, testfile: ~str, out: ~str, err: ~str) {
|
|
|
|
dump_output_file(config, testfile, out, ~"out");
|
|
|
|
dump_output_file(config, testfile, err, ~"err");
|
2011-07-30 23:11:14 -05:00
|
|
|
maybe_dump_to_stdout(config, out, err);
|
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
fn dump_output_file(config: config, testfile: ~str,
|
|
|
|
out: ~str, extension: ~str) {
|
2011-07-30 23:11:14 -05:00
|
|
|
let outfile = make_out_name(config, testfile, extension);
|
2011-10-28 23:19:59 -05:00
|
|
|
let writer = result::get(
|
2012-06-29 18:26:56 -05:00
|
|
|
io::file_writer(outfile, ~[io::create, io::truncate]));
|
2011-08-30 17:40:25 -05:00
|
|
|
writer.write_str(out);
|
2011-07-30 23:11:14 -05:00
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
fn make_out_name(config: config, testfile: ~str, extension: ~str) -> ~str {
|
|
|
|
output_base_name(config, testfile) + ~"." + extension
|
2011-07-30 23:11:14 -05:00
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
fn aux_output_dir_name(config: config, testfile: ~str) -> ~str {
|
|
|
|
output_base_name(config, testfile) + ~".libaux"
|
2012-04-10 00:41:27 -05:00
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
fn output_testname(testfile: ~str) -> ~str {
|
2012-04-10 00:41:27 -05:00
|
|
|
let parts = str::split_char(path::basename(testfile), '.');
|
2012-07-14 00:57:48 -05:00
|
|
|
str::connect(vec::slice(parts, 0u, vec::len(parts) - 1u), ~".")
|
2012-04-10 00:41:27 -05:00
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
fn output_base_name(config: config, testfile: ~str) -> ~str {
|
2011-08-30 17:40:25 -05:00
|
|
|
let base = config.build_base;
|
2012-04-10 00:41:27 -05:00
|
|
|
let filename = output_testname(testfile);
|
2012-07-30 18:01:07 -05:00
|
|
|
fmt!{"%s%s.%s", base, filename, config.stage_id}
|
2011-07-30 23:11:14 -05:00
|
|
|
}
|
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
fn maybe_dump_to_stdout(config: config, out: ~str, err: ~str) {
|
2011-07-30 23:11:14 -05:00
|
|
|
if config.verbose {
|
2012-07-30 18:01:07 -05:00
|
|
|
let sep1 = fmt!{"------%s------------------------------", ~"stdout"};
|
|
|
|
let sep2 = fmt!{"------%s------------------------------", ~"stderr"};
|
2012-07-14 00:57:48 -05:00
|
|
|
let sep3 = ~"------------------------------------------";
|
2011-08-28 02:24:28 -05:00
|
|
|
io::stdout().write_line(sep1);
|
2011-08-30 17:40:25 -05:00
|
|
|
io::stdout().write_line(out);
|
2011-08-28 02:24:28 -05:00
|
|
|
io::stdout().write_line(sep2);
|
2011-08-30 17:40:25 -05:00
|
|
|
io::stdout().write_line(err);
|
|
|
|
io::stdout().write_line(sep3);
|
2011-07-30 23:11:14 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-30 18:01:07 -05:00
|
|
|
fn error(err: ~str) { io::stdout().write_line(fmt!{"\nerror: %s", err}); }
|
2011-07-30 23:11:14 -05:00
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
fn fatal(err: ~str) -> ! { error(err); fail; }
|
2011-07-30 23:11:14 -05:00
|
|
|
|
2012-07-14 00:57:48 -05:00
|
|
|
fn fatal_procres(err: ~str, procres: procres) -> ! {
|
2011-07-30 23:11:14 -05:00
|
|
|
let msg =
|
2012-07-30 18:01:07 -05:00
|
|
|
fmt!{"\n\
|
2011-07-30 23:11:14 -05:00
|
|
|
error: %s\n\
|
|
|
|
command: %s\n\
|
|
|
|
stdout:\n\
|
|
|
|
------------------------------------------\n\
|
|
|
|
%s\n\
|
|
|
|
------------------------------------------\n\
|
|
|
|
stderr:\n\
|
|
|
|
------------------------------------------\n\
|
|
|
|
%s\n\
|
|
|
|
------------------------------------------\n\
|
|
|
|
\n",
|
2012-07-30 18:01:07 -05:00
|
|
|
err, procres.cmdline, procres.stdout, procres.stderr};
|
2011-08-11 21:14:38 -05:00
|
|
|
io::stdout().write_str(msg);
|
2011-07-30 23:11:14 -05:00
|
|
|
fail;
|
|
|
|
}
|