2014-05-20 17:15:34 +00:00
|
|
|
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
2014-01-04 20:16:57 +00:00
|
|
|
// file at the top-level directory of this distribution and at
|
2012-12-10 23:44:02 +00:00
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
2014-11-21 22:15:33 +00:00
|
|
|
|
2014-11-06 08:05:53 +00:00
|
|
|
use self::TargetLocation::*;
|
2012-12-10 23:44:02 +00:00
|
|
|
|
2014-04-16 04:56:39 +00:00
|
|
|
use common::Config;
|
2015-02-27 05:00:43 +00:00
|
|
|
use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind};
|
|
|
|
use common::{Codegen, DebugInfoLldb, DebugInfoGdb};
|
2012-12-28 16:50:27 +00:00
|
|
|
use errors;
|
2013-01-26 06:51:32 +00:00
|
|
|
use header::TestProps;
|
2014-04-24 09:35:48 +00:00
|
|
|
use header;
|
2012-12-28 16:50:27 +00:00
|
|
|
use procsrv;
|
2012-09-08 01:08:21 +00:00
|
|
|
use util::logv;
|
2015-02-27 05:00:43 +00:00
|
|
|
|
2015-01-27 20:20:58 +00:00
|
|
|
use std::env;
|
2015-02-27 05:00:43 +00:00
|
|
|
use std::ffi::OsStr;
|
|
|
|
use std::fmt;
|
|
|
|
use std::fs::{self, File};
|
|
|
|
use std::io::BufReader;
|
|
|
|
use std::io::prelude::*;
|
2014-12-30 18:51:18 +00:00
|
|
|
use std::iter::repeat;
|
2015-02-27 05:00:43 +00:00
|
|
|
use std::net::TcpStream;
|
|
|
|
use std::old_io::timer;
|
|
|
|
use std::path::{Path, PathBuf};
|
|
|
|
use std::process::{Command, Output, ExitStatus};
|
2013-07-23 18:24:54 +00:00
|
|
|
use std::str;
|
2014-08-01 01:03:20 +00:00
|
|
|
use std::time::Duration;
|
2014-02-14 01:49:11 +00:00
|
|
|
use test::MetricMap;
|
2013-07-16 01:51:20 +00:00
|
|
|
|
2015-02-27 05:00:43 +00:00
|
|
|
pub fn run(config: Config, testfile: &Path) {
|
2015-02-02 02:53:25 +00:00
|
|
|
match &*config.target {
|
2013-12-15 06:42:01 +00:00
|
|
|
|
2015-01-22 12:39:06 +00:00
|
|
|
"arm-linux-androideabi" | "aarch64-linux-android" => {
|
2013-12-15 06:42:01 +00:00
|
|
|
if !config.adb_device_status {
|
2014-10-09 19:17:22 +00:00
|
|
|
panic!("android device not available");
|
2013-12-15 06:42:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_=> { }
|
|
|
|
}
|
|
|
|
|
2013-10-31 22:15:30 +00:00
|
|
|
let mut _mm = MetricMap::new();
|
|
|
|
run_metrics(config, testfile, &mut _mm);
|
2013-07-16 01:51:20 +00:00
|
|
|
}
|
|
|
|
|
2015-02-27 05:00:43 +00:00
|
|
|
pub fn run_metrics(config: Config, testfile: &Path, mm: &mut MetricMap) {
|
2012-02-08 02:55:02 +00:00
|
|
|
if config.verbose {
|
2011-07-31 04:11:14 +00:00
|
|
|
// We're going to be dumping a lot of info. Start on a new line.
|
2013-10-14 01:48:47 +00:00
|
|
|
print!("\n\n");
|
2011-07-31 04:11:14 +00:00
|
|
|
}
|
2014-12-20 08:09:35 +00:00
|
|
|
debug!("running {:?}", testfile.display());
|
2014-04-24 09:35:48 +00:00
|
|
|
let props = header::load_props(&testfile);
|
2013-10-21 20:08:31 +00:00
|
|
|
debug!("loaded props");
|
2012-08-06 19:34:08 +00:00
|
|
|
match config.mode {
|
2014-04-16 04:56:39 +00:00
|
|
|
CompileFail => run_cfail_test(&config, &props, &testfile),
|
2015-02-11 22:09:30 +00:00
|
|
|
ParseFail => run_cfail_test(&config, &props, &testfile),
|
2014-04-16 04:56:39 +00:00
|
|
|
RunFail => run_rfail_test(&config, &props, &testfile),
|
|
|
|
RunPass => run_rpass_test(&config, &props, &testfile),
|
2014-10-07 07:00:26 +00:00
|
|
|
RunPassValgrind => run_valgrind_test(&config, &props, &testfile),
|
2014-04-16 04:56:39 +00:00
|
|
|
Pretty => run_pretty_test(&config, &props, &testfile),
|
|
|
|
DebugInfoGdb => run_debuginfo_gdb_test(&config, &props, &testfile),
|
|
|
|
DebugInfoLldb => run_debuginfo_lldb_test(&config, &props, &testfile),
|
2014-05-11 00:39:08 +00:00
|
|
|
Codegen => run_codegen_test(&config, &props, &testfile, mm),
|
2011-07-31 04:11:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-16 21:47:19 +00:00
|
|
|
fn get_output(props: &TestProps, proc_res: &ProcRes) -> String {
|
|
|
|
if props.check_stdout {
|
|
|
|
format!("{}{}", proc_res.stdout, proc_res.stderr)
|
|
|
|
} else {
|
|
|
|
proc_res.stderr.clone()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-16 04:56:39 +00:00
|
|
|
fn run_cfail_test(config: &Config, props: &TestProps, testfile: &Path) {
|
2014-02-15 21:15:03 +00:00
|
|
|
let proc_res = compile_test(config, props, testfile);
|
2011-07-31 04:11:14 +00:00
|
|
|
|
2014-02-15 21:15:03 +00:00
|
|
|
if proc_res.status.success() {
|
2015-02-22 23:49:07 +00:00
|
|
|
fatal_proc_rec(&format!("{} test compiled successfully!", config.mode)[..],
|
2014-05-15 03:47:24 +00:00
|
|
|
&proc_res);
|
2011-07-31 04:11:14 +00:00
|
|
|
}
|
|
|
|
|
2014-02-15 21:15:03 +00:00
|
|
|
check_correct_failure_status(&proc_res);
|
2012-01-04 05:01:48 +00:00
|
|
|
|
2014-09-16 21:47:19 +00:00
|
|
|
if proc_res.status.success() {
|
|
|
|
fatal("process did not return an error status");
|
|
|
|
}
|
|
|
|
|
|
|
|
let output_to_check = get_output(props, &proc_res);
|
2015-01-20 18:45:29 +00:00
|
|
|
let expected_errors = errors::load_errors(testfile);
|
2013-01-25 03:19:44 +00:00
|
|
|
if !expected_errors.is_empty() {
|
|
|
|
if !props.error_patterns.is_empty() {
|
2014-06-25 05:35:54 +00:00
|
|
|
fatal("both error pattern and expected errors specified");
|
2012-01-04 05:01:48 +00:00
|
|
|
}
|
2015-01-09 12:57:23 +00:00
|
|
|
check_expected_errors(expected_errors, testfile, &proc_res);
|
2012-01-04 05:01:48 +00:00
|
|
|
} else {
|
2015-02-02 02:53:25 +00:00
|
|
|
check_error_patterns(props, testfile, &output_to_check, &proc_res);
|
2012-01-04 05:01:48 +00:00
|
|
|
}
|
2014-05-06 08:33:24 +00:00
|
|
|
check_no_compiler_crash(&proc_res);
|
2015-02-02 02:53:25 +00:00
|
|
|
check_forbid_output(props, &output_to_check, &proc_res);
|
2011-07-31 04:11:14 +00:00
|
|
|
}
|
|
|
|
|
2014-04-16 04:56:39 +00:00
|
|
|
fn run_rfail_test(config: &Config, props: &TestProps, testfile: &Path) {
|
2014-02-15 21:15:03 +00:00
|
|
|
let proc_res = if !config.jit {
|
|
|
|
let proc_res = compile_test(config, props, testfile);
|
2011-07-31 04:11:14 +00:00
|
|
|
|
2014-02-15 21:15:03 +00:00
|
|
|
if !proc_res.status.success() {
|
2014-06-25 05:35:54 +00:00
|
|
|
fatal_proc_rec("compilation failed!", &proc_res);
|
2012-08-30 02:24:43 +00:00
|
|
|
}
|
2011-07-31 04:11:14 +00:00
|
|
|
|
2012-08-29 00:10:37 +00:00
|
|
|
exec_compiled_test(config, props, testfile)
|
|
|
|
} else {
|
|
|
|
jit_test(config, props, testfile)
|
|
|
|
};
|
2011-07-31 04:11:14 +00:00
|
|
|
|
2011-09-08 20:42:04 +00:00
|
|
|
// The value our Makefile configures valgrind to return on failure
|
2015-02-27 05:00:43 +00:00
|
|
|
const VALGRIND_ERR: i32 = 100;
|
|
|
|
if proc_res.status.code() == Some(VALGRIND_ERR) {
|
2014-06-25 05:35:54 +00:00
|
|
|
fatal_proc_rec("run-fail test isn't valgrind-clean!", &proc_res);
|
2011-08-10 20:36:57 +00:00
|
|
|
}
|
|
|
|
|
2014-09-16 21:47:19 +00:00
|
|
|
let output_to_check = get_output(props, &proc_res);
|
2014-02-15 21:15:03 +00:00
|
|
|
check_correct_failure_status(&proc_res);
|
2015-02-02 02:53:25 +00:00
|
|
|
check_error_patterns(props, testfile, &output_to_check, &proc_res);
|
2011-09-16 18:44:55 +00:00
|
|
|
}
|
|
|
|
|
2014-02-15 21:15:03 +00:00
|
|
|
fn check_correct_failure_status(proc_res: &ProcRes) {
|
2011-09-08 20:42:04 +00:00
|
|
|
// The value the rust runtime returns on failure
|
2015-02-27 05:00:43 +00:00
|
|
|
const RUST_ERR: i32 = 101;
|
|
|
|
if proc_res.status.code() != Some(RUST_ERR) {
|
2014-05-28 19:36:05 +00:00
|
|
|
fatal_proc_rec(
|
2015-02-27 05:00:43 +00:00
|
|
|
&format!("failure produced the wrong error: {}",
|
2015-02-02 02:53:25 +00:00
|
|
|
proc_res.status),
|
2014-02-15 21:15:03 +00:00
|
|
|
proc_res);
|
2011-09-08 20:42:04 +00:00
|
|
|
}
|
2011-07-31 04:11:14 +00:00
|
|
|
}
|
|
|
|
|
2014-04-16 04:56:39 +00:00
|
|
|
fn run_rpass_test(config: &Config, props: &TestProps, testfile: &Path) {
|
2012-08-29 00:10:37 +00:00
|
|
|
if !config.jit {
|
2014-02-15 21:15:03 +00:00
|
|
|
let mut proc_res = compile_test(config, props, testfile);
|
2012-08-29 00:10:37 +00:00
|
|
|
|
2014-02-15 21:15:03 +00:00
|
|
|
if !proc_res.status.success() {
|
2014-06-25 05:35:54 +00:00
|
|
|
fatal_proc_rec("compilation failed!", &proc_res);
|
2012-08-30 02:24:43 +00:00
|
|
|
}
|
2011-07-31 04:11:14 +00:00
|
|
|
|
2014-02-15 21:15:03 +00:00
|
|
|
proc_res = exec_compiled_test(config, props, testfile);
|
2011-07-31 04:11:14 +00:00
|
|
|
|
2014-02-15 21:15:03 +00:00
|
|
|
if !proc_res.status.success() {
|
2014-06-25 05:35:54 +00:00
|
|
|
fatal_proc_rec("test run failed!", &proc_res);
|
2012-08-30 02:24:43 +00:00
|
|
|
}
|
2012-08-29 00:10:37 +00:00
|
|
|
} else {
|
2014-02-15 21:15:03 +00:00
|
|
|
let proc_res = jit_test(config, props, testfile);
|
2011-07-31 04:11:14 +00:00
|
|
|
|
2014-05-15 03:47:24 +00:00
|
|
|
if !proc_res.status.success() {
|
2014-06-25 05:35:54 +00:00
|
|
|
fatal_proc_rec("jit failed!", &proc_res);
|
2014-05-15 03:47:24 +00:00
|
|
|
}
|
2012-08-29 00:10:37 +00:00
|
|
|
}
|
2011-07-31 04:11:14 +00:00
|
|
|
}
|
|
|
|
|
2014-10-07 07:00:26 +00:00
|
|
|
fn run_valgrind_test(config: &Config, props: &TestProps, testfile: &Path) {
|
|
|
|
if config.valgrind_path.is_none() {
|
2014-10-08 23:11:37 +00:00
|
|
|
assert!(!config.force_valgrind);
|
2014-10-07 07:00:26 +00:00
|
|
|
return run_rpass_test(config, props, testfile);
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut proc_res = compile_test(config, props, testfile);
|
|
|
|
|
|
|
|
if !proc_res.status.success() {
|
|
|
|
fatal_proc_rec("compilation failed!", &proc_res);
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut new_config = config.clone();
|
|
|
|
new_config.runtool = new_config.valgrind_path.clone();
|
|
|
|
proc_res = exec_compiled_test(&new_config, props, testfile);
|
|
|
|
|
|
|
|
if !proc_res.status.success() {
|
|
|
|
fatal_proc_rec("test run failed!", &proc_res);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-16 04:56:39 +00:00
|
|
|
fn run_pretty_test(config: &Config, props: &TestProps, testfile: &Path) {
|
2012-09-22 02:37:57 +00:00
|
|
|
if props.pp_exact.is_some() {
|
2014-05-25 10:17:19 +00:00
|
|
|
logv(config, "testing for exact pretty-printing".to_string());
|
2014-05-15 03:47:24 +00:00
|
|
|
} else {
|
2014-05-25 10:17:19 +00:00
|
|
|
logv(config, "testing for converging pretty-printing".to_string());
|
2014-05-15 03:47:24 +00:00
|
|
|
}
|
2011-08-01 21:10:59 +00:00
|
|
|
|
2011-08-19 22:16:48 +00:00
|
|
|
let rounds =
|
2012-12-28 16:28:36 +00:00
|
|
|
match props.pp_exact { Some(_) => 1, None => 2 };
|
2011-07-31 22:33:40 +00:00
|
|
|
|
2015-02-27 05:00:43 +00:00
|
|
|
let mut src = String::new();
|
|
|
|
File::open(testfile).unwrap().read_to_string(&mut src).unwrap();
|
2014-03-05 23:28:08 +00:00
|
|
|
let mut srcs = vec!(src);
|
2011-07-31 22:33:40 +00:00
|
|
|
|
2012-03-22 15:39:41 +00:00
|
|
|
let mut round = 0;
|
2011-07-31 22:33:40 +00:00
|
|
|
while round < rounds {
|
2014-05-28 03:44:58 +00:00
|
|
|
logv(config, format!("pretty-printing round {}", round));
|
2014-05-15 03:47:24 +00:00
|
|
|
let proc_res = print_source(config,
|
|
|
|
props,
|
|
|
|
testfile,
|
2014-07-14 23:37:25 +00:00
|
|
|
srcs[round].to_string(),
|
2015-02-02 02:53:25 +00:00
|
|
|
&props.pretty_mode);
|
2011-07-31 22:33:40 +00:00
|
|
|
|
2014-02-15 21:15:03 +00:00
|
|
|
if !proc_res.status.success() {
|
2015-02-02 02:53:25 +00:00
|
|
|
fatal_proc_rec(&format!("pretty-printing failed in round {}", round),
|
2014-02-15 21:15:03 +00:00
|
|
|
&proc_res);
|
2011-07-31 22:33:40 +00:00
|
|
|
}
|
|
|
|
|
2014-02-15 21:15:03 +00:00
|
|
|
let ProcRes{ stdout, .. } = proc_res;
|
2013-05-12 02:45:28 +00:00
|
|
|
srcs.push(stdout);
|
2011-07-31 22:33:40 +00:00
|
|
|
round += 1;
|
|
|
|
}
|
|
|
|
|
2013-07-28 16:31:37 +00:00
|
|
|
let mut expected = match props.pp_exact {
|
|
|
|
Some(ref file) => {
|
2015-02-27 05:00:43 +00:00
|
|
|
let filepath = testfile.parent().unwrap().join(file);
|
|
|
|
let mut s = String::new();
|
|
|
|
File::open(&filepath).unwrap().read_to_string(&mut s).unwrap();
|
|
|
|
s
|
2014-06-30 14:41:30 +00:00
|
|
|
}
|
2015-01-24 14:39:32 +00:00
|
|
|
None => { srcs[srcs.len() - 2].clone() }
|
2014-06-30 14:41:30 +00:00
|
|
|
};
|
2015-01-24 14:39:32 +00:00
|
|
|
let mut actual = srcs[srcs.len() - 1].clone();
|
2011-08-03 23:25:38 +00:00
|
|
|
|
2012-09-22 02:37:57 +00:00
|
|
|
if props.pp_exact.is_some() {
|
2011-08-03 22:36:45 +00:00
|
|
|
// Now we have to care about line endings
|
2014-05-25 10:17:19 +00:00
|
|
|
let cr = "\r".to_string();
|
2015-02-02 02:53:25 +00:00
|
|
|
actual = actual.replace(&cr, "").to_string();
|
|
|
|
expected = expected.replace(&cr, "").to_string();
|
2011-08-03 22:36:45 +00:00
|
|
|
}
|
2011-07-31 22:33:40 +00:00
|
|
|
|
2015-02-02 02:53:25 +00:00
|
|
|
compare_source(&expected, &actual);
|
2011-07-31 22:33:40 +00:00
|
|
|
|
2014-07-22 23:39:10 +00:00
|
|
|
// If we're only making sure that the output matches then just stop here
|
|
|
|
if props.pretty_compare_only { return; }
|
|
|
|
|
2011-07-31 22:33:40 +00:00
|
|
|
// Finally, let's make sure it actually appears to remain valid code
|
2014-02-15 21:15:03 +00:00
|
|
|
let proc_res = typecheck_source(config, props, testfile, actual);
|
2011-07-31 22:33:40 +00:00
|
|
|
|
2014-02-15 21:15:03 +00:00
|
|
|
if !proc_res.status.success() {
|
2014-06-25 05:35:54 +00:00
|
|
|
fatal_proc_rec("pretty-printed source does not typecheck", &proc_res);
|
2011-07-31 22:33:40 +00:00
|
|
|
}
|
2014-05-11 00:39:08 +00:00
|
|
|
if props.no_pretty_expanded { return }
|
2011-07-31 22:33:40 +00:00
|
|
|
|
2014-04-16 05:29:02 +00:00
|
|
|
// additionally, run `--pretty expanded` and try to build it.
|
2014-07-14 23:37:25 +00:00
|
|
|
let proc_res = print_source(config, props, testfile, srcs[round].clone(), "expanded");
|
2014-04-16 05:29:02 +00:00
|
|
|
if !proc_res.status.success() {
|
2014-06-25 05:35:54 +00:00
|
|
|
fatal_proc_rec("pretty-printing (expanded) failed", &proc_res);
|
2014-04-16 05:29:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
let ProcRes{ stdout: expanded_src, .. } = proc_res;
|
|
|
|
let proc_res = typecheck_source(config, props, testfile, expanded_src);
|
|
|
|
if !proc_res.status.success() {
|
2014-06-25 05:35:54 +00:00
|
|
|
fatal_proc_rec("pretty-printed source (expanded) does not typecheck",
|
2014-05-15 03:47:24 +00:00
|
|
|
&proc_res);
|
2014-04-16 05:29:02 +00:00
|
|
|
}
|
|
|
|
|
2012-08-02 00:30:05 +00:00
|
|
|
return;
|
2011-07-31 22:33:40 +00:00
|
|
|
|
2014-04-16 05:29:02 +00:00
|
|
|
fn print_source(config: &Config,
|
|
|
|
props: &TestProps,
|
|
|
|
testfile: &Path,
|
2014-05-22 23:57:53 +00:00
|
|
|
src: String,
|
2014-04-16 05:29:02 +00:00
|
|
|
pretty_type: &str) -> ProcRes {
|
2014-06-11 21:52:38 +00:00
|
|
|
let aux_dir = aux_output_dir_name(config, testfile);
|
2014-05-15 03:47:24 +00:00
|
|
|
compose_and_run(config,
|
|
|
|
testfile,
|
|
|
|
make_pp_args(config,
|
|
|
|
props,
|
|
|
|
testfile,
|
2014-05-25 10:17:19 +00:00
|
|
|
pretty_type.to_string()),
|
2014-05-15 03:47:24 +00:00
|
|
|
props.exec_env.clone(),
|
2015-02-02 02:53:25 +00:00
|
|
|
&config.compile_lib_path,
|
2015-02-27 05:00:43 +00:00
|
|
|
Some(aux_dir.to_str().unwrap()),
|
2014-05-15 03:47:24 +00:00
|
|
|
Some(src))
|
2011-07-31 22:33:40 +00:00
|
|
|
}
|
|
|
|
|
2014-05-11 00:39:08 +00:00
|
|
|
fn make_pp_args(config: &Config,
|
|
|
|
props: &TestProps,
|
|
|
|
testfile: &Path,
|
2014-05-22 23:57:53 +00:00
|
|
|
pretty_type: String) -> ProcArgs {
|
2014-05-11 00:39:08 +00:00
|
|
|
let aux_dir = aux_output_dir_name(config, testfile);
|
2013-09-27 00:21:59 +00:00
|
|
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
2014-05-25 10:17:19 +00:00
|
|
|
let mut args = vec!("-".to_string(),
|
2015-01-20 18:57:10 +00:00
|
|
|
"-Zunstable-options".to_string(),
|
2014-05-25 10:17:19 +00:00
|
|
|
"--pretty".to_string(),
|
2014-05-15 03:47:24 +00:00
|
|
|
pretty_type,
|
2014-05-28 03:44:58 +00:00
|
|
|
format!("--target={}", config.target),
|
2014-05-25 10:17:19 +00:00
|
|
|
"-L".to_string(),
|
2015-02-27 05:00:43 +00:00
|
|
|
aux_dir.to_str().unwrap().to_string());
|
2014-09-17 19:56:31 +00:00
|
|
|
args.extend(split_maybe_args(&config.target_rustcflags).into_iter());
|
|
|
|
args.extend(split_maybe_args(&props.compile_flags).into_iter());
|
2014-05-15 03:47:24 +00:00
|
|
|
return ProcArgs {
|
2015-02-27 05:00:43 +00:00
|
|
|
prog: config.rustc_path.to_str().unwrap().to_string(),
|
2014-05-15 03:47:24 +00:00
|
|
|
args: args,
|
|
|
|
};
|
2011-07-31 22:33:40 +00:00
|
|
|
}
|
|
|
|
|
2013-05-12 02:45:28 +00:00
|
|
|
fn compare_source(expected: &str, actual: &str) {
|
2011-07-31 22:33:40 +00:00
|
|
|
if expected != actual {
|
2014-06-25 05:35:54 +00:00
|
|
|
error("pretty-printed source does not match expected source");
|
2013-10-14 01:48:47 +00:00
|
|
|
println!("\n\
|
2011-07-31 22:33:40 +00:00
|
|
|
expected:\n\
|
|
|
|
------------------------------------------\n\
|
2013-09-29 20:18:51 +00:00
|
|
|
{}\n\
|
2011-07-31 22:33:40 +00:00
|
|
|
------------------------------------------\n\
|
|
|
|
actual:\n\
|
|
|
|
------------------------------------------\n\
|
2013-09-29 20:18:51 +00:00
|
|
|
{}\n\
|
2011-07-31 22:33:40 +00:00
|
|
|
------------------------------------------\n\
|
|
|
|
\n",
|
2012-08-23 00:24:52 +00:00
|
|
|
expected, actual);
|
2014-10-09 19:17:22 +00:00
|
|
|
panic!();
|
2011-07-31 22:33:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-16 04:56:39 +00:00
|
|
|
fn typecheck_source(config: &Config, props: &TestProps,
|
2014-05-22 23:57:53 +00:00
|
|
|
testfile: &Path, src: String) -> ProcRes {
|
2013-05-12 02:45:28 +00:00
|
|
|
let args = make_typecheck_args(config, props, testfile);
|
|
|
|
compose_and_run_compiler(config, props, testfile, args, Some(src))
|
2011-08-01 02:12:33 +00:00
|
|
|
}
|
|
|
|
|
2014-04-16 04:56:39 +00:00
|
|
|
fn make_typecheck_args(config: &Config, props: &TestProps, testfile: &Path) -> ProcArgs {
|
2013-09-27 00:21:59 +00:00
|
|
|
let aux_dir = aux_output_dir_name(config, testfile);
|
2014-01-19 02:23:46 +00:00
|
|
|
let target = if props.force_host {
|
2015-02-02 02:53:25 +00:00
|
|
|
&*config.host
|
2014-01-19 02:23:46 +00:00
|
|
|
} else {
|
2015-02-02 02:53:25 +00:00
|
|
|
&*config.target
|
2014-01-19 02:23:46 +00:00
|
|
|
};
|
2013-09-27 00:21:59 +00:00
|
|
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
2014-05-25 10:17:19 +00:00
|
|
|
let mut args = vec!("-".to_string(),
|
2015-01-20 18:57:10 +00:00
|
|
|
"-Zno-trans".to_string(),
|
2014-05-25 10:17:19 +00:00
|
|
|
"--crate-type=lib".to_string(),
|
2014-05-28 03:44:58 +00:00
|
|
|
format!("--target={}", target),
|
2014-05-25 10:17:19 +00:00
|
|
|
"-L".to_string(),
|
2015-02-27 05:00:43 +00:00
|
|
|
config.build_base.to_str().unwrap().to_string(),
|
2014-05-25 10:17:19 +00:00
|
|
|
"-L".to_string(),
|
2015-02-27 05:00:43 +00:00
|
|
|
aux_dir.to_str().unwrap().to_string());
|
2014-09-17 19:56:31 +00:00
|
|
|
args.extend(split_maybe_args(&config.target_rustcflags).into_iter());
|
|
|
|
args.extend(split_maybe_args(&props.compile_flags).into_iter());
|
2013-09-27 00:21:59 +00:00
|
|
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
2014-05-15 03:47:24 +00:00
|
|
|
return ProcArgs {
|
2015-02-27 05:00:43 +00:00
|
|
|
prog: config.rustc_path.to_str().unwrap().to_string(),
|
2014-05-15 03:47:24 +00:00
|
|
|
args: args,
|
|
|
|
};
|
2011-07-31 22:33:40 +00:00
|
|
|
}
|
2011-07-31 04:44:30 +00:00
|
|
|
}
|
|
|
|
|
2014-04-16 04:56:39 +00:00
|
|
|
fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
|
|
|
|
let mut config = Config {
|
2014-02-19 16:11:36 +00:00
|
|
|
target_rustcflags: cleanup_debug_info_options(&config.target_rustcflags),
|
|
|
|
host_rustcflags: cleanup_debug_info_options(&config.host_rustcflags),
|
|
|
|
.. config.clone()
|
2013-02-27 18:35:56 +00:00
|
|
|
};
|
2014-02-19 16:11:36 +00:00
|
|
|
|
2013-05-12 02:45:28 +00:00
|
|
|
let config = &mut config;
|
2014-07-24 09:09:41 +00:00
|
|
|
let DebuggerCommands {
|
|
|
|
commands,
|
|
|
|
check_lines,
|
2014-10-29 06:13:29 +00:00
|
|
|
breakpoint_lines
|
2014-07-24 09:09:41 +00:00
|
|
|
} = parse_debugger_commands(testfile, "gdb");
|
2014-06-26 06:15:14 +00:00
|
|
|
let mut cmds = commands.connect("\n");
|
2013-02-27 18:35:56 +00:00
|
|
|
|
2014-08-01 23:40:21 +00:00
|
|
|
// compile test file (it should have 'compile-flags:-g' in the header)
|
2014-04-24 09:35:48 +00:00
|
|
|
let compiler_run_result = compile_test(config, props, testfile);
|
|
|
|
if !compiler_run_result.status.success() {
|
2014-06-25 05:35:54 +00:00
|
|
|
fatal_proc_rec("compilation failed!", &compiler_run_result);
|
2013-02-09 18:09:19 +00:00
|
|
|
}
|
|
|
|
|
2013-09-27 00:21:59 +00:00
|
|
|
let exe_file = make_exe_name(config, testfile);
|
2013-11-04 06:53:01 +00:00
|
|
|
|
2014-04-24 09:35:48 +00:00
|
|
|
let debugger_run_result;
|
2015-02-02 02:53:25 +00:00
|
|
|
match &*config.target {
|
2015-01-22 12:39:06 +00:00
|
|
|
"arm-linux-androideabi" | "aarch64-linux-android" => {
|
2013-11-04 06:53:01 +00:00
|
|
|
|
2015-01-27 06:36:25 +00:00
|
|
|
cmds = cmds.replace("run", "continue");
|
2013-12-15 06:42:01 +00:00
|
|
|
|
|
|
|
// write debugger script
|
2015-01-27 06:36:25 +00:00
|
|
|
let mut script_str = String::with_capacity(2048);
|
|
|
|
script_str.push_str("set charset UTF-8\n");
|
2015-02-27 05:00:43 +00:00
|
|
|
script_str.push_str(&format!("file {}\n", exe_file.to_str().unwrap()));
|
2015-01-27 06:36:25 +00:00
|
|
|
script_str.push_str("target remote :5039\n");
|
2015-02-11 05:28:00 +00:00
|
|
|
script_str.push_str(&format!("set solib-search-path \
|
|
|
|
./{}/stage2/lib/rustlib/{}/lib/\n",
|
|
|
|
config.host, config.target));
|
2015-01-27 06:36:25 +00:00
|
|
|
for line in breakpoint_lines.iter() {
|
|
|
|
script_str.push_str(&format!("break {:?}:{}\n",
|
2015-02-27 05:00:43 +00:00
|
|
|
testfile.file_name().unwrap()
|
|
|
|
.to_string_lossy(),
|
2015-02-22 23:49:07 +00:00
|
|
|
*line)[..]);
|
2015-01-27 06:36:25 +00:00
|
|
|
}
|
|
|
|
script_str.push_str(&cmds);
|
2015-02-27 05:00:43 +00:00
|
|
|
script_str.push_str("\nquit\n");
|
2015-01-27 06:36:25 +00:00
|
|
|
|
2013-12-15 06:42:01 +00:00
|
|
|
debug!("script_str = {}", script_str);
|
2014-05-20 06:19:56 +00:00
|
|
|
dump_output_file(config,
|
|
|
|
testfile,
|
2015-02-02 02:53:25 +00:00
|
|
|
&script_str,
|
2014-05-20 06:19:56 +00:00
|
|
|
"debugger.script");
|
2013-11-04 06:53:01 +00:00
|
|
|
|
|
|
|
|
2014-05-15 03:47:24 +00:00
|
|
|
procsrv::run("",
|
2015-02-02 02:53:25 +00:00
|
|
|
&config.adb_path,
|
2014-06-11 21:52:38 +00:00
|
|
|
None,
|
2014-11-17 08:39:01 +00:00
|
|
|
&[
|
2014-05-25 10:17:19 +00:00
|
|
|
"push".to_string(),
|
2015-02-27 05:00:43 +00:00
|
|
|
exe_file.to_str().unwrap().to_string(),
|
2014-05-15 03:47:24 +00:00
|
|
|
config.adb_test_dir.clone()
|
|
|
|
],
|
2014-05-25 10:17:19 +00:00
|
|
|
vec!(("".to_string(), "".to_string())),
|
|
|
|
Some("".to_string()))
|
2015-02-02 02:53:25 +00:00
|
|
|
.expect(&format!("failed to exec `{:?}`", config.adb_path));
|
2014-05-15 03:47:24 +00:00
|
|
|
|
|
|
|
procsrv::run("",
|
2015-02-02 02:53:25 +00:00
|
|
|
&config.adb_path,
|
2014-06-11 21:52:38 +00:00
|
|
|
None,
|
2014-11-17 08:39:01 +00:00
|
|
|
&[
|
2014-05-25 10:17:19 +00:00
|
|
|
"forward".to_string(),
|
|
|
|
"tcp:5039".to_string(),
|
|
|
|
"tcp:5039".to_string()
|
2014-05-15 03:47:24 +00:00
|
|
|
],
|
2014-05-25 10:17:19 +00:00
|
|
|
vec!(("".to_string(), "".to_string())),
|
|
|
|
Some("".to_string()))
|
2015-02-02 02:53:25 +00:00
|
|
|
.expect(&format!("failed to exec `{:?}`", config.adb_path));
|
2014-05-15 03:47:24 +00:00
|
|
|
|
2014-05-28 03:44:58 +00:00
|
|
|
let adb_arg = format!("export LD_LIBRARY_PATH={}; \
|
2015-01-27 06:36:25 +00:00
|
|
|
gdbserver{} :5039 {}/{}",
|
2014-05-28 03:44:58 +00:00
|
|
|
config.adb_test_dir.clone(),
|
2015-01-27 06:36:25 +00:00
|
|
|
if config.target.contains("aarch64")
|
|
|
|
{"64"} else {""},
|
2014-05-28 03:44:58 +00:00
|
|
|
config.adb_test_dir.clone(),
|
2015-02-27 05:00:43 +00:00
|
|
|
exe_file.file_name().unwrap().to_str()
|
|
|
|
.unwrap());
|
2014-05-15 03:47:24 +00:00
|
|
|
|
|
|
|
let mut process = procsrv::run_background("",
|
2015-02-02 02:53:25 +00:00
|
|
|
&config.adb_path
|
|
|
|
,
|
2014-06-11 21:52:38 +00:00
|
|
|
None,
|
2014-11-17 08:39:01 +00:00
|
|
|
&[
|
2014-05-25 10:17:19 +00:00
|
|
|
"shell".to_string(),
|
2014-05-15 03:47:24 +00:00
|
|
|
adb_arg.clone()
|
|
|
|
],
|
2014-05-25 10:17:19 +00:00
|
|
|
vec!(("".to_string(),
|
|
|
|
"".to_string())),
|
|
|
|
Some("".to_string()))
|
2015-02-02 02:53:25 +00:00
|
|
|
.expect(&format!("failed to exec `{:?}`", config.adb_path));
|
2013-12-15 06:42:01 +00:00
|
|
|
loop {
|
|
|
|
//waiting 1 second for gdbserver start
|
2014-08-01 01:03:20 +00:00
|
|
|
timer::sleep(Duration::milliseconds(1000));
|
2015-02-27 05:00:43 +00:00
|
|
|
if TcpStream::connect("127.0.0.1:5039").is_ok() {
|
|
|
|
break
|
2013-12-15 06:42:01 +00:00
|
|
|
}
|
|
|
|
}
|
2013-11-04 06:53:01 +00:00
|
|
|
|
2015-02-27 05:00:43 +00:00
|
|
|
let tool_path = match config.android_cross_path.to_str() {
|
2014-05-25 10:17:19 +00:00
|
|
|
Some(x) => x.to_string(),
|
2014-06-25 05:35:54 +00:00
|
|
|
None => fatal("cannot find android cross path")
|
2014-05-13 18:44:30 +00:00
|
|
|
};
|
2013-12-15 06:42:01 +00:00
|
|
|
|
|
|
|
let debugger_script = make_out_name(config, testfile, "debugger.script");
|
|
|
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
2014-05-15 03:47:24 +00:00
|
|
|
let debugger_opts =
|
2014-05-25 10:17:19 +00:00
|
|
|
vec!("-quiet".to_string(),
|
|
|
|
"-batch".to_string(),
|
|
|
|
"-nx".to_string(),
|
2015-02-27 05:00:43 +00:00
|
|
|
format!("-command={}", debugger_script.to_str().unwrap()));
|
2013-12-15 06:42:01 +00:00
|
|
|
|
2014-09-22 15:28:35 +00:00
|
|
|
let mut gdb_path = tool_path;
|
2015-01-22 12:39:06 +00:00
|
|
|
gdb_path.push_str(&format!("/bin/{}-gdb", config.target));
|
2014-05-15 03:47:24 +00:00
|
|
|
let procsrv::Result {
|
|
|
|
out,
|
|
|
|
err,
|
|
|
|
status
|
|
|
|
} = procsrv::run("",
|
2015-02-02 02:53:25 +00:00
|
|
|
&gdb_path,
|
2014-06-11 21:52:38 +00:00
|
|
|
None,
|
2015-02-02 02:53:25 +00:00
|
|
|
&debugger_opts,
|
2014-05-25 10:17:19 +00:00
|
|
|
vec!(("".to_string(), "".to_string())),
|
2014-03-05 23:28:08 +00:00
|
|
|
None)
|
2015-02-02 02:53:25 +00:00
|
|
|
.expect(&format!("failed to exec `{:?}`", gdb_path));
|
2013-12-15 06:42:01 +00:00
|
|
|
let cmdline = {
|
2014-03-05 23:28:08 +00:00
|
|
|
let cmdline = make_cmdline("",
|
2015-01-22 12:39:06 +00:00
|
|
|
&format!("{}-gdb", config.target),
|
2015-02-02 02:53:25 +00:00
|
|
|
&debugger_opts);
|
2014-05-28 03:44:58 +00:00
|
|
|
logv(config, format!("executing {}", cmdline));
|
2013-12-15 06:42:01 +00:00
|
|
|
cmdline
|
|
|
|
};
|
|
|
|
|
2014-04-24 09:35:48 +00:00
|
|
|
debugger_run_result = ProcRes {
|
2015-02-27 05:00:43 +00:00
|
|
|
status: Status::Normal(status),
|
2014-04-24 09:35:48 +00:00
|
|
|
stdout: out,
|
|
|
|
stderr: err,
|
|
|
|
cmdline: cmdline
|
|
|
|
};
|
2015-02-27 05:00:43 +00:00
|
|
|
if process.kill().is_err() {
|
2015-01-27 06:36:25 +00:00
|
|
|
println!("Adb process is already finished.");
|
|
|
|
}
|
2013-11-04 06:53:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
_=> {
|
2014-07-30 13:56:42 +00:00
|
|
|
let rust_src_root = find_rust_src_root(config)
|
|
|
|
.expect("Could not find Rust source root");
|
2014-07-24 09:09:41 +00:00
|
|
|
let rust_pp_module_rel_path = Path::new("./src/etc");
|
|
|
|
let rust_pp_module_abs_path = rust_src_root.join(rust_pp_module_rel_path)
|
2015-02-27 05:00:43 +00:00
|
|
|
.to_str()
|
2014-07-24 09:09:41 +00:00
|
|
|
.unwrap()
|
|
|
|
.to_string();
|
2013-11-04 06:53:01 +00:00
|
|
|
// write debugger script
|
2014-08-20 10:53:50 +00:00
|
|
|
let mut script_str = String::with_capacity(2048);
|
|
|
|
|
|
|
|
script_str.push_str("set charset UTF-8\n");
|
|
|
|
script_str.push_str("show version\n");
|
|
|
|
|
|
|
|
match config.gdb_version {
|
|
|
|
Some(ref version) => {
|
2014-08-27 13:18:16 +00:00
|
|
|
println!("NOTE: compiletest thinks it is using GDB version {}",
|
2015-02-02 02:53:25 +00:00
|
|
|
version);
|
2014-08-27 13:18:16 +00:00
|
|
|
|
2015-02-02 02:53:25 +00:00
|
|
|
if header::gdb_version_to_int(version) >
|
2014-08-20 10:53:50 +00:00
|
|
|
header::gdb_version_to_int("7.4") {
|
|
|
|
// Add the directory containing the pretty printers to
|
2014-12-03 22:48:18 +00:00
|
|
|
// GDB's script auto loading safe path
|
2014-08-20 10:53:50 +00:00
|
|
|
script_str.push_str(
|
2015-02-02 02:53:25 +00:00
|
|
|
&format!("add-auto-load-safe-path {}\n",
|
2015-02-27 05:00:43 +00:00
|
|
|
rust_pp_module_abs_path.replace(r"\", r"\\"))
|
2015-02-02 02:53:25 +00:00
|
|
|
);
|
2014-08-20 10:53:50 +00:00
|
|
|
}
|
|
|
|
}
|
2014-08-27 13:18:16 +00:00
|
|
|
_ => {
|
|
|
|
println!("NOTE: compiletest does not know which version of \
|
|
|
|
GDB it is using");
|
|
|
|
}
|
2014-08-20 10:53:50 +00:00
|
|
|
}
|
|
|
|
|
2014-10-29 06:13:29 +00:00
|
|
|
// The following line actually doesn't have to do anything with
|
|
|
|
// pretty printing, it just tells GDB to print values on one line:
|
|
|
|
script_str.push_str("set print pretty off\n");
|
|
|
|
|
2014-12-03 22:48:18 +00:00
|
|
|
// Add the pretty printer directory to GDB's source-file search path
|
2015-02-27 05:00:43 +00:00
|
|
|
script_str.push_str(&format!("directory {}\n",
|
|
|
|
rust_pp_module_abs_path));
|
2014-12-03 22:48:18 +00:00
|
|
|
|
2014-08-20 10:53:50 +00:00
|
|
|
// Load the target executable
|
2015-01-04 04:43:24 +00:00
|
|
|
script_str.push_str(&format!("file {}\n",
|
2015-02-27 05:00:43 +00:00
|
|
|
exe_file.to_str().unwrap()
|
|
|
|
.replace(r"\", r"\\")));
|
2014-08-20 10:53:50 +00:00
|
|
|
|
2014-10-29 06:13:29 +00:00
|
|
|
// Add line breakpoints
|
2015-01-31 17:20:46 +00:00
|
|
|
for line in &breakpoint_lines {
|
2015-01-20 23:45:07 +00:00
|
|
|
script_str.push_str(&format!("break '{}':{}\n",
|
2015-02-27 05:00:43 +00:00
|
|
|
testfile.file_name().unwrap()
|
|
|
|
.to_string_lossy(),
|
|
|
|
*line));
|
2014-10-29 06:13:29 +00:00
|
|
|
}
|
|
|
|
|
2015-02-02 02:53:25 +00:00
|
|
|
script_str.push_str(&cmds);
|
2015-02-27 05:00:43 +00:00
|
|
|
script_str.push_str("\nquit\n");
|
2014-08-20 10:53:50 +00:00
|
|
|
|
2013-11-04 06:53:01 +00:00
|
|
|
debug!("script_str = {}", script_str);
|
2014-05-20 06:19:56 +00:00
|
|
|
dump_output_file(config,
|
|
|
|
testfile,
|
2015-02-02 02:53:25 +00:00
|
|
|
&script_str,
|
2014-05-20 06:19:56 +00:00
|
|
|
"debugger.script");
|
2013-11-04 06:53:01 +00:00
|
|
|
|
|
|
|
// run debugger script with gdb
|
2015-02-27 05:00:43 +00:00
|
|
|
fn debugger() -> &'static str {
|
|
|
|
if cfg!(windows) {"gdb.exe"} else {"gdb"}
|
2014-05-15 03:47:24 +00:00
|
|
|
}
|
2013-11-04 06:53:01 +00:00
|
|
|
|
|
|
|
let debugger_script = make_out_name(config, testfile, "debugger.script");
|
|
|
|
|
|
|
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
2014-05-15 03:47:24 +00:00
|
|
|
let debugger_opts =
|
2014-05-25 10:17:19 +00:00
|
|
|
vec!("-quiet".to_string(),
|
|
|
|
"-batch".to_string(),
|
|
|
|
"-nx".to_string(),
|
2015-02-27 05:00:43 +00:00
|
|
|
format!("-command={}", debugger_script.to_str().unwrap()));
|
2014-07-24 09:09:41 +00:00
|
|
|
|
|
|
|
let proc_args = ProcArgs {
|
2015-02-27 05:00:43 +00:00
|
|
|
prog: debugger().to_string(),
|
2014-05-15 03:47:24 +00:00
|
|
|
args: debugger_opts,
|
|
|
|
};
|
2014-07-24 09:09:41 +00:00
|
|
|
|
|
|
|
let environment = vec![("PYTHONPATH".to_string(), rust_pp_module_abs_path)];
|
|
|
|
|
2014-04-24 09:35:48 +00:00
|
|
|
debugger_run_result = compose_and_run(config,
|
|
|
|
testfile,
|
|
|
|
proc_args,
|
2014-07-24 09:09:41 +00:00
|
|
|
environment,
|
2015-02-02 02:53:25 +00:00
|
|
|
&config.run_lib_path,
|
2014-06-11 21:52:38 +00:00
|
|
|
None,
|
2014-04-24 09:35:48 +00:00
|
|
|
None);
|
2013-11-04 06:53:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-24 09:35:48 +00:00
|
|
|
if !debugger_run_result.status.success() {
|
2014-06-25 05:35:54 +00:00
|
|
|
fatal("gdb failed to execute");
|
2013-02-09 18:09:19 +00:00
|
|
|
}
|
2014-04-24 09:35:48 +00:00
|
|
|
|
2015-02-02 02:53:25 +00:00
|
|
|
check_debugger_output(&debugger_run_result, &check_lines);
|
2014-07-24 09:09:41 +00:00
|
|
|
}
|
|
|
|
|
2015-02-27 05:00:43 +00:00
|
|
|
fn find_rust_src_root(config: &Config) -> Option<PathBuf> {
|
2014-07-24 09:09:41 +00:00
|
|
|
let mut path = config.src_base.clone();
|
|
|
|
let path_postfix = Path::new("src/etc/lldb_batchmode.py");
|
|
|
|
|
|
|
|
while path.pop() {
|
2014-10-31 05:03:52 +00:00
|
|
|
if path.join(&path_postfix).is_file() {
|
2014-07-24 09:09:41 +00:00
|
|
|
return Some(path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return None;
|
2014-04-24 09:35:48 +00:00
|
|
|
}
|
|
|
|
|
2014-05-11 00:39:08 +00:00
|
|
|
fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path) {
|
2014-04-24 09:35:48 +00:00
|
|
|
if config.lldb_python_dir.is_none() {
|
2014-06-25 05:35:54 +00:00
|
|
|
fatal("Can't run LLDB test because LLDB's python path is not set.");
|
2014-04-24 09:35:48 +00:00
|
|
|
}
|
|
|
|
|
2014-05-11 00:39:08 +00:00
|
|
|
let mut config = Config {
|
2014-04-24 09:35:48 +00:00
|
|
|
target_rustcflags: cleanup_debug_info_options(&config.target_rustcflags),
|
|
|
|
host_rustcflags: cleanup_debug_info_options(&config.host_rustcflags),
|
|
|
|
.. config.clone()
|
|
|
|
};
|
|
|
|
|
|
|
|
let config = &mut config;
|
|
|
|
|
2014-08-01 23:40:21 +00:00
|
|
|
// compile test file (it should have 'compile-flags:-g' in the header)
|
2014-04-24 09:35:48 +00:00
|
|
|
let compile_result = compile_test(config, props, testfile);
|
|
|
|
if !compile_result.status.success() {
|
2014-06-25 05:35:54 +00:00
|
|
|
fatal_proc_rec("compilation failed!", &compile_result);
|
2014-04-24 09:35:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
let exe_file = make_exe_name(config, testfile);
|
|
|
|
|
2014-10-02 09:35:24 +00:00
|
|
|
match config.lldb_version {
|
|
|
|
Some(ref version) => {
|
|
|
|
println!("NOTE: compiletest thinks it is using LLDB version {}",
|
2015-02-02 02:53:25 +00:00
|
|
|
version);
|
2014-10-02 09:35:24 +00:00
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
println!("NOTE: compiletest does not know which version of \
|
|
|
|
LLDB it is using");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-24 09:35:48 +00:00
|
|
|
// Parse debugger commands etc from test files
|
|
|
|
let DebuggerCommands {
|
|
|
|
commands,
|
|
|
|
check_lines,
|
2014-07-24 09:09:41 +00:00
|
|
|
breakpoint_lines,
|
|
|
|
..
|
2014-04-24 09:35:48 +00:00
|
|
|
} = parse_debugger_commands(testfile, "lldb");
|
|
|
|
|
|
|
|
// Write debugger script:
|
|
|
|
// We don't want to hang when calling `quit` while the process is still running
|
2014-05-22 23:57:53 +00:00
|
|
|
let mut script_str = String::from_str("settings set auto-confirm true\n");
|
2014-04-24 09:35:48 +00:00
|
|
|
|
2014-07-09 09:33:48 +00:00
|
|
|
// Make LLDB emit its version, so we have it documented in the test output
|
|
|
|
script_str.push_str("version\n");
|
|
|
|
|
|
|
|
// Switch LLDB into "Rust mode"
|
2014-10-08 16:28:30 +00:00
|
|
|
let rust_src_root = find_rust_src_root(config)
|
|
|
|
.expect("Could not find Rust source root");
|
|
|
|
let rust_pp_module_rel_path = Path::new("./src/etc/lldb_rust_formatters.py");
|
|
|
|
let rust_pp_module_abs_path = rust_src_root.join(rust_pp_module_rel_path)
|
2015-02-27 05:00:43 +00:00
|
|
|
.to_str()
|
2014-10-08 16:28:30 +00:00
|
|
|
.unwrap()
|
|
|
|
.to_string();
|
|
|
|
|
2015-02-27 05:00:43 +00:00
|
|
|
script_str.push_str(&format!("command script import {}\n",
|
|
|
|
&rust_pp_module_abs_path[..])[..]);
|
2014-07-09 09:33:48 +00:00
|
|
|
script_str.push_str("type summary add --no-value ");
|
|
|
|
script_str.push_str("--python-function lldb_rust_formatters.print_val ");
|
|
|
|
script_str.push_str("-x \".*\" --category Rust\n");
|
|
|
|
script_str.push_str("type category enable Rust\n");
|
|
|
|
|
2014-04-24 09:35:48 +00:00
|
|
|
// Set breakpoints on every line that contains the string "#break"
|
2015-01-31 17:20:46 +00:00
|
|
|
for line in &breakpoint_lines {
|
2015-02-02 02:53:25 +00:00
|
|
|
script_str.push_str(&format!("breakpoint set --line {}\n", line));
|
2014-04-24 09:35:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Append the other commands
|
2015-01-31 17:20:46 +00:00
|
|
|
for line in &commands {
|
2015-02-02 02:53:25 +00:00
|
|
|
script_str.push_str(line);
|
2014-04-24 09:35:48 +00:00
|
|
|
script_str.push_str("\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Finally, quit the debugger
|
2015-02-27 05:00:43 +00:00
|
|
|
script_str.push_str("\nquit\n");
|
2014-04-24 09:35:48 +00:00
|
|
|
|
|
|
|
// Write the script into a file
|
|
|
|
debug!("script_str = {}", script_str);
|
2014-05-20 06:19:56 +00:00
|
|
|
dump_output_file(config,
|
|
|
|
testfile,
|
2015-02-02 02:53:25 +00:00
|
|
|
&script_str,
|
2014-05-20 06:19:56 +00:00
|
|
|
"debugger.script");
|
2014-04-24 09:35:48 +00:00
|
|
|
let debugger_script = make_out_name(config, testfile, "debugger.script");
|
|
|
|
|
|
|
|
// Let LLDB execute the script via lldb_batchmode.py
|
2014-10-08 16:28:30 +00:00
|
|
|
let debugger_run_result = run_lldb(config,
|
|
|
|
&exe_file,
|
|
|
|
&debugger_script,
|
|
|
|
&rust_src_root);
|
2014-04-24 09:35:48 +00:00
|
|
|
|
|
|
|
if !debugger_run_result.status.success() {
|
2014-06-25 05:35:54 +00:00
|
|
|
fatal_proc_rec("Error while running LLDB", &debugger_run_result);
|
2014-04-24 09:35:48 +00:00
|
|
|
}
|
|
|
|
|
2015-02-02 02:53:25 +00:00
|
|
|
check_debugger_output(&debugger_run_result, &check_lines);
|
2014-04-24 09:35:48 +00:00
|
|
|
|
2014-10-08 16:28:30 +00:00
|
|
|
fn run_lldb(config: &Config,
|
|
|
|
test_executable: &Path,
|
|
|
|
debugger_script: &Path,
|
|
|
|
rust_src_root: &Path)
|
|
|
|
-> ProcRes {
|
2014-04-24 09:35:48 +00:00
|
|
|
// Prepare the lldb_batchmode which executes the debugger script
|
2015-02-27 05:00:43 +00:00
|
|
|
let lldb_script_path = rust_src_root.join("src/etc/lldb_batchmode.py");
|
2014-10-08 16:28:30 +00:00
|
|
|
|
2014-05-05 21:33:55 +00:00
|
|
|
let mut cmd = Command::new("python");
|
2015-02-27 05:00:43 +00:00
|
|
|
cmd.arg(&lldb_script_path)
|
2014-05-05 21:33:55 +00:00
|
|
|
.arg(test_executable)
|
|
|
|
.arg(debugger_script)
|
2015-02-27 05:00:43 +00:00
|
|
|
.env("PYTHONPATH", config.lldb_python_dir.as_ref().unwrap());
|
2014-04-24 09:35:48 +00:00
|
|
|
|
2015-02-27 05:00:43 +00:00
|
|
|
let (status, out, err) = match cmd.output() {
|
|
|
|
Ok(Output { status, stdout, stderr }) => {
|
2014-04-24 09:35:48 +00:00
|
|
|
(status,
|
2015-02-27 05:00:43 +00:00
|
|
|
String::from_utf8(stdout).unwrap(),
|
|
|
|
String::from_utf8(stderr).unwrap())
|
2014-04-24 09:35:48 +00:00
|
|
|
},
|
|
|
|
Err(e) => {
|
2015-02-02 02:53:25 +00:00
|
|
|
fatal(&format!("Failed to setup Python process for \
|
|
|
|
LLDB script: {}", e))
|
2014-04-24 09:35:48 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-02-02 02:53:25 +00:00
|
|
|
dump_output(config, test_executable, &out, &err);
|
2014-04-24 09:35:48 +00:00
|
|
|
return ProcRes {
|
2015-02-27 05:00:43 +00:00
|
|
|
status: Status::Normal(status),
|
2014-04-24 09:35:48 +00:00
|
|
|
stdout: out,
|
|
|
|
stderr: err,
|
2015-01-20 23:45:07 +00:00
|
|
|
cmdline: format!("{:?}", cmd)
|
2014-04-24 09:35:48 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-15 03:47:24 +00:00
|
|
|
struct DebuggerCommands {
|
2014-05-22 23:57:53 +00:00
|
|
|
commands: Vec<String>,
|
|
|
|
check_lines: Vec<String>,
|
2014-05-15 03:47:24 +00:00
|
|
|
breakpoint_lines: Vec<uint>,
|
2014-04-24 09:35:48 +00:00
|
|
|
}
|
|
|
|
|
2014-05-15 03:47:24 +00:00
|
|
|
fn parse_debugger_commands(file_path: &Path, debugger_prefix: &str)
|
|
|
|
-> DebuggerCommands {
|
2014-05-20 06:19:56 +00:00
|
|
|
let command_directive = format!("{}-command", debugger_prefix);
|
|
|
|
let check_directive = format!("{}-check", debugger_prefix);
|
2014-04-24 09:35:48 +00:00
|
|
|
|
|
|
|
let mut breakpoint_lines = vec!();
|
|
|
|
let mut commands = vec!();
|
|
|
|
let mut check_lines = vec!();
|
|
|
|
let mut counter = 1;
|
2015-02-27 05:00:43 +00:00
|
|
|
let reader = BufReader::new(File::open(file_path).unwrap());
|
2014-04-24 09:35:48 +00:00
|
|
|
for line in reader.lines() {
|
|
|
|
match line {
|
|
|
|
Ok(line) => {
|
2015-01-27 02:21:15 +00:00
|
|
|
if line.contains("#break") {
|
2014-04-24 09:35:48 +00:00
|
|
|
breakpoint_lines.push(counter);
|
|
|
|
}
|
|
|
|
|
2014-05-15 03:47:24 +00:00
|
|
|
header::parse_name_value_directive(
|
2015-02-02 02:53:25 +00:00
|
|
|
&line,
|
|
|
|
&command_directive).map(|cmd| {
|
2014-05-15 03:47:24 +00:00
|
|
|
commands.push(cmd)
|
|
|
|
});
|
2014-04-24 09:35:48 +00:00
|
|
|
|
2014-05-15 03:47:24 +00:00
|
|
|
header::parse_name_value_directive(
|
2015-02-02 02:53:25 +00:00
|
|
|
&line,
|
|
|
|
&check_directive).map(|cmd| {
|
2014-05-15 03:47:24 +00:00
|
|
|
check_lines.push(cmd)
|
|
|
|
});
|
2014-04-24 09:35:48 +00:00
|
|
|
}
|
|
|
|
Err(e) => {
|
2015-02-02 02:53:25 +00:00
|
|
|
fatal(&format!("Error while parsing debugger commands: {}", e))
|
2014-04-24 09:35:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
counter += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
DebuggerCommands {
|
|
|
|
commands: commands,
|
|
|
|
check_lines: check_lines,
|
2014-07-24 09:09:41 +00:00
|
|
|
breakpoint_lines: breakpoint_lines,
|
2014-04-24 09:35:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-22 23:57:53 +00:00
|
|
|
fn cleanup_debug_info_options(options: &Option<String>) -> Option<String> {
|
2014-04-24 09:35:48 +00:00
|
|
|
if options.is_none() {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove options that are either unwanted (-O) or may lead to duplicates due to RUSTFLAGS.
|
2014-05-15 03:47:24 +00:00
|
|
|
let options_to_remove = [
|
2014-05-25 10:17:19 +00:00
|
|
|
"-O".to_string(),
|
|
|
|
"-g".to_string(),
|
|
|
|
"--debuginfo".to_string()
|
2014-05-15 03:47:24 +00:00
|
|
|
];
|
|
|
|
let new_options =
|
2014-09-15 03:27:36 +00:00
|
|
|
split_maybe_args(options).into_iter()
|
2014-05-15 03:47:24 +00:00
|
|
|
.filter(|x| !options_to_remove.contains(x))
|
2014-05-22 23:57:53 +00:00
|
|
|
.collect::<Vec<String>>()
|
2014-06-25 05:35:54 +00:00
|
|
|
.connect(" ");
|
2014-04-24 09:35:48 +00:00
|
|
|
Some(new_options)
|
|
|
|
}
|
|
|
|
|
2014-05-22 23:57:53 +00:00
|
|
|
fn check_debugger_output(debugger_run_result: &ProcRes, check_lines: &[String]) {
|
2013-05-14 09:52:12 +00:00
|
|
|
let num_check_lines = check_lines.len();
|
2013-02-09 18:09:19 +00:00
|
|
|
if num_check_lines > 0 {
|
2013-08-31 21:41:35 +00:00
|
|
|
// Allow check lines to leave parts unspecified (e.g., uninitialized
|
|
|
|
// bits in the wrong case of an enum) with the notation "[...]".
|
2014-05-22 23:57:53 +00:00
|
|
|
let check_fragments: Vec<Vec<String>> =
|
2014-03-05 23:28:08 +00:00
|
|
|
check_lines.iter().map(|s| {
|
2015-02-02 02:53:25 +00:00
|
|
|
s
|
2014-05-15 03:47:24 +00:00
|
|
|
.trim()
|
2015-02-19 13:36:58 +00:00
|
|
|
.split("[...]")
|
2014-05-25 10:17:19 +00:00
|
|
|
.map(|x| x.to_string())
|
2014-05-15 03:47:24 +00:00
|
|
|
.collect()
|
2014-03-05 23:28:08 +00:00
|
|
|
}).collect();
|
2013-02-09 18:09:19 +00:00
|
|
|
// check if each line in props.check_lines appears in the
|
|
|
|
// output (in order)
|
2015-01-24 14:39:32 +00:00
|
|
|
let mut i = 0;
|
2015-01-27 02:21:15 +00:00
|
|
|
for line in debugger_run_result.stdout.lines() {
|
2013-08-31 21:41:35 +00:00
|
|
|
let mut rest = line.trim();
|
|
|
|
let mut first = true;
|
|
|
|
let mut failed = false;
|
2015-01-31 17:20:46 +00:00
|
|
|
for frag in &check_fragments[i] {
|
2013-08-31 21:41:35 +00:00
|
|
|
let found = if first {
|
2015-02-02 02:53:25 +00:00
|
|
|
if rest.starts_with(frag) {
|
2014-05-15 03:47:24 +00:00
|
|
|
Some(0)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
2013-08-31 21:41:35 +00:00
|
|
|
} else {
|
2015-02-19 13:36:58 +00:00
|
|
|
rest.find(frag)
|
2013-08-31 21:41:35 +00:00
|
|
|
};
|
|
|
|
match found {
|
|
|
|
None => {
|
|
|
|
failed = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Some(i) => {
|
2015-01-18 00:15:52 +00:00
|
|
|
rest = &rest[(i + frag.len())..];
|
2013-08-31 21:41:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
first = false;
|
|
|
|
}
|
|
|
|
if !failed && rest.len() == 0 {
|
2015-01-24 14:39:32 +00:00
|
|
|
i += 1;
|
2013-02-09 18:09:19 +00:00
|
|
|
}
|
|
|
|
if i == num_check_lines {
|
|
|
|
// all lines checked
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if i != num_check_lines {
|
2015-02-02 02:53:25 +00:00
|
|
|
fatal_proc_rec(&format!("line not found in debugger output: {}",
|
|
|
|
check_lines.get(i).unwrap()),
|
2014-05-15 03:47:24 +00:00
|
|
|
debugger_run_result);
|
2013-02-09 18:09:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-12 02:45:28 +00:00
|
|
|
fn check_error_patterns(props: &TestProps,
|
2012-08-24 22:28:43 +00:00
|
|
|
testfile: &Path,
|
2014-09-16 21:47:19 +00:00
|
|
|
output_to_check: &str,
|
2014-02-15 21:15:03 +00:00
|
|
|
proc_res: &ProcRes) {
|
2013-06-09 01:38:47 +00:00
|
|
|
if props.error_patterns.is_empty() {
|
2015-02-02 02:53:25 +00:00
|
|
|
fatal(&format!("no error pattern specified in {:?}", testfile.display()));
|
2011-07-31 04:11:14 +00:00
|
|
|
}
|
2015-01-24 14:39:32 +00:00
|
|
|
let mut next_err_idx = 0;
|
2014-07-14 23:37:25 +00:00
|
|
|
let mut next_err_pat = &props.error_patterns[next_err_idx];
|
2012-04-06 18:36:43 +00:00
|
|
|
let mut done = false;
|
2015-01-27 02:21:15 +00:00
|
|
|
for line in output_to_check.lines() {
|
2015-02-02 02:53:25 +00:00
|
|
|
if line.contains(next_err_pat) {
|
2014-07-14 23:37:25 +00:00
|
|
|
debug!("found error pattern {}", next_err_pat);
|
2015-01-24 14:39:32 +00:00
|
|
|
next_err_idx += 1;
|
2013-05-14 09:52:12 +00:00
|
|
|
if next_err_idx == props.error_patterns.len() {
|
2013-10-21 20:08:31 +00:00
|
|
|
debug!("found all error patterns");
|
2012-04-06 18:36:43 +00:00
|
|
|
done = true;
|
|
|
|
break;
|
2011-07-31 04:11:14 +00:00
|
|
|
}
|
2014-07-14 23:37:25 +00:00
|
|
|
next_err_pat = &props.error_patterns[next_err_idx];
|
2011-07-31 04:11:14 +00:00
|
|
|
}
|
|
|
|
}
|
2012-08-02 00:30:05 +00:00
|
|
|
if done { return; }
|
2011-07-31 04:11:14 +00:00
|
|
|
|
2015-01-07 16:58:31 +00:00
|
|
|
let missing_patterns = &props.error_patterns[next_err_idx..];
|
2015-01-24 14:39:32 +00:00
|
|
|
if missing_patterns.len() == 1 {
|
2015-02-02 02:53:25 +00:00
|
|
|
fatal_proc_rec(&format!("error pattern '{}' not found!", missing_patterns[0]),
|
2014-05-15 03:47:24 +00:00
|
|
|
proc_res);
|
2011-07-31 04:11:14 +00:00
|
|
|
} else {
|
2015-01-31 17:20:46 +00:00
|
|
|
for pattern in missing_patterns {
|
2015-02-02 02:53:25 +00:00
|
|
|
error(&format!("error pattern '{}' not found!", *pattern));
|
2011-07-31 04:11:14 +00:00
|
|
|
}
|
2014-06-25 05:35:54 +00:00
|
|
|
fatal_proc_rec("multiple error patterns not found", proc_res);
|
2011-07-31 04:11:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-06 08:33:24 +00:00
|
|
|
fn check_no_compiler_crash(proc_res: &ProcRes) {
|
2015-01-27 02:21:15 +00:00
|
|
|
for line in proc_res.stderr.lines() {
|
2014-05-06 08:33:24 +00:00
|
|
|
if line.starts_with("error: internal compiler error:") {
|
2014-06-25 05:35:54 +00:00
|
|
|
fatal_proc_rec("compiler encountered internal error",
|
2014-05-06 08:33:24 +00:00
|
|
|
proc_res);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-16 21:47:19 +00:00
|
|
|
fn check_forbid_output(props: &TestProps,
|
|
|
|
output_to_check: &str,
|
|
|
|
proc_res: &ProcRes) {
|
2015-01-31 17:20:46 +00:00
|
|
|
for pat in &props.forbid_output {
|
2015-02-02 02:53:25 +00:00
|
|
|
if output_to_check.contains(pat) {
|
2014-09-16 21:47:19 +00:00
|
|
|
fatal_proc_rec("forbidden pattern found in compiler output", proc_res);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-09 12:57:23 +00:00
|
|
|
fn check_expected_errors(expected_errors: Vec<errors::ExpectedError> ,
|
2012-08-24 22:28:43 +00:00
|
|
|
testfile: &Path,
|
2014-02-15 21:15:03 +00:00
|
|
|
proc_res: &ProcRes) {
|
2012-01-04 05:01:48 +00:00
|
|
|
|
|
|
|
// true if we found the error in question
|
2014-12-30 18:51:18 +00:00
|
|
|
let mut found_flags: Vec<_> = repeat(false).take(expected_errors.len()).collect();
|
2012-01-04 05:01:48 +00:00
|
|
|
|
2014-02-15 21:15:03 +00:00
|
|
|
if proc_res.status.success() {
|
2014-06-25 05:35:54 +00:00
|
|
|
fatal("process did not return an error status");
|
2012-01-04 05:01:48 +00:00
|
|
|
}
|
|
|
|
|
2013-08-10 03:09:47 +00:00
|
|
|
let prefixes = expected_errors.iter().map(|ee| {
|
2015-01-20 23:45:07 +00:00
|
|
|
format!("{}:{}:", testfile.display(), ee.line)
|
2015-02-27 05:00:43 +00:00
|
|
|
}).collect::<Vec<String>>();
|
|
|
|
|
|
|
|
fn prefix_matches(line: &str, prefix: &str) -> bool {
|
|
|
|
use std::ascii::AsciiExt;
|
|
|
|
// On windows just translate all '\' path separators to '/'
|
|
|
|
let line = line.replace(r"\", "/");
|
|
|
|
if cfg!(windows) {
|
|
|
|
line.to_ascii_lowercase().starts_with(&prefix.to_ascii_lowercase())
|
|
|
|
} else {
|
|
|
|
line.starts_with(prefix)
|
|
|
|
}
|
2013-07-23 18:24:54 +00:00
|
|
|
}
|
|
|
|
|
2015-01-12 04:18:52 +00:00
|
|
|
// A multi-line error will have followup lines which will always
|
|
|
|
// start with one of these strings.
|
|
|
|
fn continuation( line: &str) -> bool {
|
|
|
|
line.starts_with(" expected") ||
|
|
|
|
line.starts_with(" found") ||
|
|
|
|
// 1234
|
|
|
|
// Should have 4 spaces: see issue 18946
|
|
|
|
line.starts_with("(")
|
|
|
|
}
|
|
|
|
|
2012-01-04 05:01:48 +00: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.
|
2015-01-27 02:21:15 +00:00
|
|
|
for line in proc_res.stderr.lines() {
|
2012-03-22 15:39:41 +00:00
|
|
|
let mut was_expected = false;
|
2013-08-03 16:45:23 +00:00
|
|
|
for (i, ee) in expected_errors.iter().enumerate() {
|
2014-07-14 23:37:25 +00:00
|
|
|
if !found_flags[i] {
|
2013-10-21 20:08:31 +00:00
|
|
|
debug!("prefix={} ee.kind={} ee.msg={} line={}",
|
2015-02-02 02:53:25 +00:00
|
|
|
prefixes[i],
|
2014-05-15 03:47:24 +00:00
|
|
|
ee.kind,
|
|
|
|
ee.msg,
|
|
|
|
line);
|
2015-02-02 02:53:25 +00:00
|
|
|
if (prefix_matches(line, &prefixes[i]) || continuation(line)) &&
|
|
|
|
line.contains(&ee.kind) &&
|
|
|
|
line.contains(&ee.msg) {
|
2014-10-23 15:42:21 +00:00
|
|
|
found_flags[i] = true;
|
2012-01-04 05:01:48 +00:00
|
|
|
was_expected = true;
|
2012-04-06 03:58:23 +00:00
|
|
|
break;
|
2012-01-04 05:01:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ignore this msg which gets printed at the end
|
2013-06-10 07:32:36 +00:00
|
|
|
if line.contains("aborting due to") {
|
2012-01-04 05:01:48 +00:00
|
|
|
was_expected = true;
|
|
|
|
}
|
|
|
|
|
2013-05-29 18:10:16 +00:00
|
|
|
if !was_expected && is_compiler_error_or_warning(line) {
|
2015-02-02 02:53:25 +00:00
|
|
|
fatal_proc_rec(&format!("unexpected compiler error or warning: '{}'",
|
|
|
|
line),
|
2014-02-15 21:15:03 +00:00
|
|
|
proc_res);
|
2012-01-04 05:01:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-07 18:19:15 +00:00
|
|
|
for (i, &flag) in found_flags.iter().enumerate() {
|
|
|
|
if !flag {
|
2014-07-14 23:37:25 +00:00
|
|
|
let ee = &expected_errors[i];
|
2015-02-02 02:53:25 +00:00
|
|
|
fatal_proc_rec(&format!("expected {} on line {} not found: {}",
|
|
|
|
ee.kind, ee.line, ee.msg),
|
2014-05-15 03:47:24 +00:00
|
|
|
proc_res);
|
2012-01-04 05:01:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-12 02:45:28 +00:00
|
|
|
fn is_compiler_error_or_warning(line: &str) -> bool {
|
2015-01-24 14:39:32 +00:00
|
|
|
let mut i = 0;
|
2012-09-11 06:50:16 +00:00
|
|
|
return
|
|
|
|
scan_until_char(line, ':', &mut i) &&
|
|
|
|
scan_char(line, ':', &mut i) &&
|
|
|
|
scan_integer(line, &mut i) &&
|
|
|
|
scan_char(line, ':', &mut i) &&
|
|
|
|
scan_integer(line, &mut i) &&
|
|
|
|
scan_char(line, ':', &mut i) &&
|
|
|
|
scan_char(line, ' ', &mut i) &&
|
|
|
|
scan_integer(line, &mut i) &&
|
|
|
|
scan_char(line, ':', &mut i) &&
|
|
|
|
scan_integer(line, &mut i) &&
|
|
|
|
scan_char(line, ' ', &mut i) &&
|
2013-05-12 02:45:28 +00:00
|
|
|
(scan_string(line, "error", &mut i) ||
|
|
|
|
scan_string(line, "warning", &mut i));
|
2012-09-11 06:50:16 +00:00
|
|
|
}
|
|
|
|
|
2013-05-12 02:45:28 +00:00
|
|
|
fn scan_until_char(haystack: &str, needle: char, idx: &mut uint) -> bool {
|
2012-09-11 06:50:16 +00:00
|
|
|
if *idx >= haystack.len() {
|
|
|
|
return false;
|
|
|
|
}
|
2015-01-18 00:15:52 +00:00
|
|
|
let opt = haystack[(*idx)..].find(needle);
|
2012-09-11 06:50:16 +00:00
|
|
|
if opt.is_none() {
|
|
|
|
return false;
|
|
|
|
}
|
2013-08-03 23:59:24 +00:00
|
|
|
*idx = opt.unwrap();
|
2012-09-11 06:50:16 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-05-12 02:45:28 +00:00
|
|
|
fn scan_char(haystack: &str, needle: char, idx: &mut uint) -> bool {
|
2012-09-11 06:50:16 +00:00
|
|
|
if *idx >= haystack.len() {
|
|
|
|
return false;
|
|
|
|
}
|
2013-06-10 11:46:36 +00:00
|
|
|
let range = haystack.char_range_at(*idx);
|
2012-11-27 04:05:19 +00:00
|
|
|
if range.ch != needle {
|
2012-09-11 06:50:16 +00:00
|
|
|
return false;
|
|
|
|
}
|
2012-11-27 04:05:19 +00:00
|
|
|
*idx = range.next;
|
2012-09-11 06:50:16 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-05-12 02:45:28 +00:00
|
|
|
fn scan_integer(haystack: &str, idx: &mut uint) -> bool {
|
2012-09-11 06:50:16 +00:00
|
|
|
let mut i = *idx;
|
|
|
|
while i < haystack.len() {
|
2013-06-10 11:46:36 +00:00
|
|
|
let range = haystack.char_range_at(i);
|
2012-11-27 04:05:19 +00:00
|
|
|
if range.ch < '0' || '9' < range.ch {
|
2012-09-11 06:50:16 +00:00
|
|
|
break;
|
|
|
|
}
|
2012-11-27 04:05:19 +00:00
|
|
|
i = range.next;
|
2012-09-11 06:50:16 +00:00
|
|
|
}
|
|
|
|
if i == *idx {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
*idx = i;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-05-12 02:45:28 +00:00
|
|
|
fn scan_string(haystack: &str, needle: &str, idx: &mut uint) -> bool {
|
2012-09-11 06:50:16 +00:00
|
|
|
let mut haystack_i = *idx;
|
2015-01-24 14:39:32 +00:00
|
|
|
let mut needle_i = 0;
|
2012-09-11 06:50:16 +00:00
|
|
|
while needle_i < needle.len() {
|
|
|
|
if haystack_i >= haystack.len() {
|
|
|
|
return false;
|
|
|
|
}
|
2013-06-10 11:46:36 +00:00
|
|
|
let range = haystack.char_range_at(haystack_i);
|
2012-11-27 04:05:19 +00:00
|
|
|
haystack_i = range.next;
|
|
|
|
if !scan_char(needle, range.ch, &mut needle_i) {
|
2012-09-11 06:50:16 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*idx = haystack_i;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-05-15 03:47:24 +00:00
|
|
|
struct ProcArgs {
|
2014-05-22 23:57:53 +00:00
|
|
|
prog: String,
|
|
|
|
args: Vec<String>,
|
2014-05-15 03:47:24 +00:00
|
|
|
}
|
2011-07-31 04:11:14 +00:00
|
|
|
|
2014-05-15 03:47:24 +00:00
|
|
|
struct ProcRes {
|
2015-02-27 05:00:43 +00:00
|
|
|
status: Status,
|
2014-05-22 23:57:53 +00:00
|
|
|
stdout: String,
|
|
|
|
stderr: String,
|
|
|
|
cmdline: String,
|
2014-05-15 03:47:24 +00:00
|
|
|
}
|
2011-07-31 04:11:14 +00:00
|
|
|
|
2015-02-27 05:00:43 +00:00
|
|
|
enum Status {
|
|
|
|
Parsed(i32),
|
|
|
|
Normal(ExitStatus),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Status {
|
|
|
|
fn code(&self) -> Option<i32> {
|
|
|
|
match *self {
|
|
|
|
Status::Parsed(i) => Some(i),
|
|
|
|
Status::Normal(ref e) => e.code(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn success(&self) -> bool {
|
|
|
|
match *self {
|
|
|
|
Status::Parsed(i) => i == 0,
|
|
|
|
Status::Normal(ref e) => e.success(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for Status {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
match *self {
|
|
|
|
Status::Parsed(i) => write!(f, "exit code: {}", i),
|
|
|
|
Status::Normal(ref e) => e.fmt(f),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-16 04:56:39 +00:00
|
|
|
fn compile_test(config: &Config, props: &TestProps,
|
2013-01-26 06:51:32 +00:00
|
|
|
testfile: &Path) -> ProcRes {
|
2014-11-17 08:39:01 +00:00
|
|
|
compile_test_(config, props, testfile, &[])
|
2012-08-29 00:10:37 +00:00
|
|
|
}
|
|
|
|
|
2014-04-16 04:56:39 +00:00
|
|
|
fn jit_test(config: &Config, props: &TestProps, testfile: &Path) -> ProcRes {
|
2014-11-17 08:39:01 +00:00
|
|
|
compile_test_(config, props, testfile, &["--jit".to_string()])
|
2012-08-29 00:10:37 +00:00
|
|
|
}
|
|
|
|
|
2014-04-16 04:56:39 +00:00
|
|
|
fn compile_test_(config: &Config, props: &TestProps,
|
2014-05-22 23:57:53 +00:00
|
|
|
testfile: &Path, extra_args: &[String]) -> ProcRes {
|
2013-09-27 00:21:59 +00:00
|
|
|
let aux_dir = aux_output_dir_name(config, testfile);
|
|
|
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
2014-09-17 19:56:31 +00:00
|
|
|
let mut link_args = vec!("-L".to_string(),
|
2015-02-27 05:00:43 +00:00
|
|
|
aux_dir.to_str().unwrap().to_string());
|
2015-02-13 07:33:44 +00:00
|
|
|
link_args.extend(extra_args.iter().cloned());
|
2014-03-05 23:28:08 +00:00
|
|
|
let args = make_compile_args(config,
|
|
|
|
props,
|
2014-09-17 19:56:31 +00:00
|
|
|
link_args,
|
2014-11-21 18:50:44 +00:00
|
|
|
|a, b| TargetLocation::ThisFile(make_exe_name(a, b)), testfile);
|
2013-05-12 02:45:28 +00:00
|
|
|
compose_and_run_compiler(config, props, testfile, args, None)
|
2012-03-28 21:58:31 +00:00
|
|
|
}
|
|
|
|
|
2014-04-16 04:56:39 +00:00
|
|
|
fn exec_compiled_test(config: &Config, props: &TestProps,
|
2013-01-26 06:51:32 +00:00
|
|
|
testfile: &Path) -> ProcRes {
|
2013-03-16 01:06:19 +00:00
|
|
|
|
2013-07-02 19:47:32 +00:00
|
|
|
let env = props.exec_env.clone();
|
2013-03-16 01:06:19 +00:00
|
|
|
|
2015-02-02 02:53:25 +00:00
|
|
|
match &*config.target {
|
2013-05-01 09:52:08 +00:00
|
|
|
|
2015-01-22 12:39:06 +00:00
|
|
|
"arm-linux-androideabi" | "aarch64-linux-android" => {
|
2013-12-15 06:42:01 +00:00
|
|
|
_arm_exec_compiled_test(config, props, testfile, env)
|
2013-05-04 01:35:07 +00:00
|
|
|
}
|
2013-05-03 15:49:18 +00:00
|
|
|
|
2013-05-04 01:35:07 +00:00
|
|
|
_=> {
|
2014-06-11 21:52:38 +00:00
|
|
|
let aux_dir = aux_output_dir_name(config, testfile);
|
2014-05-15 03:47:24 +00:00
|
|
|
compose_and_run(config,
|
|
|
|
testfile,
|
2013-05-04 01:35:07 +00:00
|
|
|
make_run_args(config, props, testfile),
|
|
|
|
env,
|
2015-02-02 02:53:25 +00:00
|
|
|
&config.run_lib_path,
|
2015-02-27 05:00:43 +00:00
|
|
|
Some(aux_dir.to_str().unwrap()),
|
2014-05-15 03:47:24 +00:00
|
|
|
None)
|
2013-05-01 09:52:08 +00:00
|
|
|
}
|
|
|
|
}
|
2012-03-28 21:58:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn compose_and_run_compiler(
|
2014-04-16 04:56:39 +00:00
|
|
|
config: &Config,
|
2013-05-12 02:45:28 +00:00
|
|
|
props: &TestProps,
|
2012-08-24 22:28:43 +00:00
|
|
|
testfile: &Path,
|
2013-01-26 06:51:32 +00:00
|
|
|
args: ProcArgs,
|
2014-05-22 23:57:53 +00:00
|
|
|
input: Option<String>) -> ProcRes {
|
2012-03-28 21:58:31 +00:00
|
|
|
|
2013-01-25 03:19:44 +00:00
|
|
|
if !props.aux_builds.is_empty() {
|
2012-08-24 22:28:43 +00:00
|
|
|
ensure_dir(&aux_output_dir_name(config, testfile));
|
2012-04-10 05:41:27 +00:00
|
|
|
}
|
|
|
|
|
2013-09-27 00:21:59 +00:00
|
|
|
let aux_dir = aux_output_dir_name(config, testfile);
|
|
|
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
2015-02-27 05:00:43 +00:00
|
|
|
let extra_link_args = vec!("-L".to_string(), aux_dir.to_str().unwrap().to_string());
|
2012-04-10 05:41:27 +00:00
|
|
|
|
2015-01-31 17:20:46 +00:00
|
|
|
for rel_ab in &props.aux_builds {
|
2015-02-02 02:53:25 +00:00
|
|
|
let abs_ab = config.aux_base.join(rel_ab);
|
2014-04-24 09:35:48 +00:00
|
|
|
let aux_props = header::load_props(&abs_ab);
|
2014-09-17 19:56:31 +00:00
|
|
|
let mut crate_type = if aux_props.no_prefer_dynamic {
|
2014-03-05 23:28:08 +00:00
|
|
|
Vec::new()
|
2014-02-10 19:33:33 +00:00
|
|
|
} else {
|
2014-05-25 10:17:19 +00:00
|
|
|
vec!("--crate-type=dylib".to_string())
|
2014-02-10 19:33:33 +00:00
|
|
|
};
|
2014-09-17 19:56:31 +00:00
|
|
|
crate_type.extend(extra_link_args.clone().into_iter());
|
2012-04-13 16:19:07 +00:00
|
|
|
let aux_args =
|
2014-03-05 23:28:08 +00:00
|
|
|
make_compile_args(config,
|
|
|
|
&aux_props,
|
2014-09-17 19:56:31 +00:00
|
|
|
crate_type,
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 23:27:54 +00:00
|
|
|
|a,b| {
|
|
|
|
let f = make_lib_name(a, b, testfile);
|
2015-02-27 05:00:43 +00:00
|
|
|
let parent = f.parent().unwrap();
|
|
|
|
TargetLocation::ThisDirectory(parent.to_path_buf())
|
2014-05-15 03:47:24 +00:00
|
|
|
},
|
|
|
|
&abs_ab);
|
|
|
|
let auxres = compose_and_run(config,
|
|
|
|
&abs_ab,
|
|
|
|
aux_args,
|
|
|
|
Vec::new(),
|
2015-02-02 02:53:25 +00:00
|
|
|
&config.compile_lib_path,
|
2015-02-27 05:00:43 +00:00
|
|
|
Some(aux_dir.to_str().unwrap()),
|
2014-05-15 03:47:24 +00:00
|
|
|
None);
|
2013-11-12 01:37:14 +00:00
|
|
|
if !auxres.status.success() {
|
2014-05-28 19:36:05 +00:00
|
|
|
fatal_proc_rec(
|
2015-02-02 02:53:25 +00:00
|
|
|
&format!("auxiliary build of {:?} failed to compile: ",
|
|
|
|
abs_ab.display()),
|
2013-05-12 02:45:28 +00:00
|
|
|
&auxres);
|
2012-03-01 18:36:22 +00:00
|
|
|
}
|
2013-05-01 09:52:08 +00:00
|
|
|
|
2015-02-02 02:53:25 +00:00
|
|
|
match &*config.target {
|
2015-01-22 12:39:06 +00:00
|
|
|
"arm-linux-androideabi" | "aarch64-linux-android" => {
|
2013-12-15 06:42:01 +00:00
|
|
|
_arm_push_aux_shared_library(config, testfile);
|
2013-05-01 09:52:08 +00:00
|
|
|
}
|
2014-05-15 03:47:24 +00:00
|
|
|
_ => {}
|
2013-05-01 09:52:08 +00:00
|
|
|
}
|
2012-02-28 05:23:49 +00:00
|
|
|
}
|
|
|
|
|
2014-05-15 03:47:24 +00:00
|
|
|
compose_and_run(config,
|
|
|
|
testfile,
|
|
|
|
args,
|
|
|
|
Vec::new(),
|
2015-02-02 02:53:25 +00:00
|
|
|
&config.compile_lib_path,
|
2015-02-27 05:00:43 +00:00
|
|
|
Some(aux_dir.to_str().unwrap()),
|
2014-05-15 03:47:24 +00:00
|
|
|
input)
|
2011-07-31 04:11:14 +00:00
|
|
|
}
|
|
|
|
|
2012-08-24 22:28:43 +00:00
|
|
|
fn ensure_dir(path: &Path) {
|
2013-10-26 00:04:37 +00:00
|
|
|
if path.is_dir() { return; }
|
2015-02-27 05:00:43 +00:00
|
|
|
fs::create_dir(path).unwrap();
|
2012-04-10 05:41:27 +00:00
|
|
|
}
|
|
|
|
|
2014-04-16 04:56:39 +00:00
|
|
|
fn compose_and_run(config: &Config, testfile: &Path,
|
2013-05-12 02:45:28 +00:00
|
|
|
ProcArgs{ args, prog }: ProcArgs,
|
2014-05-22 23:57:53 +00:00
|
|
|
procenv: Vec<(String, String)> ,
|
2013-05-12 02:45:28 +00:00
|
|
|
lib_path: &str,
|
2014-06-11 21:52:38 +00:00
|
|
|
aux_path: Option<&str>,
|
2014-05-22 23:57:53 +00:00
|
|
|
input: Option<String>) -> ProcRes {
|
2012-08-02 00:30:05 +00:00
|
|
|
return program_output(config, testfile, lib_path,
|
2014-06-11 21:52:38 +00:00
|
|
|
prog, aux_path, args, procenv, input);
|
2011-07-31 04:11:14 +00:00
|
|
|
}
|
|
|
|
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 23:27:54 +00:00
|
|
|
enum TargetLocation {
|
2015-02-27 05:00:43 +00:00
|
|
|
ThisFile(PathBuf),
|
|
|
|
ThisDirectory(PathBuf),
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 23:27:54 +00:00
|
|
|
}
|
|
|
|
|
2015-01-05 03:05:29 +00:00
|
|
|
fn make_compile_args<F>(config: &Config,
|
|
|
|
props: &TestProps,
|
|
|
|
extras: Vec<String> ,
|
|
|
|
xform: F,
|
|
|
|
testfile: &Path)
|
|
|
|
-> ProcArgs where
|
|
|
|
F: FnOnce(&Config, &Path) -> TargetLocation,
|
|
|
|
{
|
2013-09-27 00:21:59 +00:00
|
|
|
let xform_file = xform(config, testfile);
|
2014-01-17 18:18:02 +00:00
|
|
|
let target = if props.force_host {
|
2015-02-02 02:53:25 +00:00
|
|
|
&*config.host
|
2014-01-17 18:18:02 +00:00
|
|
|
} else {
|
2015-02-02 02:53:25 +00:00
|
|
|
&*config.target
|
2014-01-17 18:18:02 +00:00
|
|
|
};
|
2013-09-27 00:21:59 +00:00
|
|
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
2015-02-27 05:00:43 +00:00
|
|
|
let mut args = vec!(testfile.to_str().unwrap().to_string(),
|
2014-05-25 10:17:19 +00:00
|
|
|
"-L".to_string(),
|
2015-02-27 05:00:43 +00:00
|
|
|
config.build_base.to_str().unwrap().to_string(),
|
2014-05-28 03:44:58 +00:00
|
|
|
format!("--target={}", target));
|
2015-02-02 02:53:25 +00:00
|
|
|
args.push_all(&extras);
|
2014-02-10 19:33:33 +00:00
|
|
|
if !props.no_prefer_dynamic {
|
2014-05-25 10:17:19 +00:00
|
|
|
args.push("-C".to_string());
|
|
|
|
args.push("prefer-dynamic".to_string());
|
2014-02-10 19:33:33 +00:00
|
|
|
}
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 23:27:54 +00:00
|
|
|
let path = match xform_file {
|
2014-11-21 18:50:44 +00:00
|
|
|
TargetLocation::ThisFile(path) => {
|
2014-05-25 10:17:19 +00:00
|
|
|
args.push("-o".to_string());
|
2014-05-15 03:47:24 +00:00
|
|
|
path
|
|
|
|
}
|
2014-11-21 18:50:44 +00:00
|
|
|
TargetLocation::ThisDirectory(path) => {
|
2014-05-25 10:17:19 +00:00
|
|
|
args.push("--out-dir".to_string());
|
2014-05-15 03:47:24 +00:00
|
|
|
path
|
|
|
|
}
|
Redesign output flags for rustc
This commit removes the -c, --emit-llvm, -s, --rlib, --dylib, --staticlib,
--lib, and --bin flags from rustc, adding the following flags:
* --emit=[asm,ir,bc,obj,link]
* --crate-type=[dylib,rlib,staticlib,bin,lib]
The -o option has also been redefined to be used for *all* flavors of outputs.
This means that we no longer ignore it for libraries. The --out-dir remains the
same as before.
The new logic for files that rustc emits is as follows:
1. Output types are dictated by the --emit flag. The default value is
--emit=link, and this option can be passed multiple times and have all
options stacked on one another.
2. Crate types are dictated by the --crate-type flag and the #[crate_type]
attribute. The flags can be passed many times and stack with the crate
attribute.
3. If the -o flag is specified, and only one output type is specified, the
output will be emitted at this location. If more than one output type is
specified, then the filename of -o is ignored, and all output goes in the
directory that -o specifies. The -o option always ignores the --out-dir
option.
4. If the --out-dir flag is specified, all output goes in this directory.
5. If -o and --out-dir are both not present, all output goes in the current
directory of the process.
6. When multiple output types are specified, the filestem of all output is the
same as the name of the CrateId (derived from a crate attribute or from the
filestem of the crate file).
Closes #7791
Closes #11056
Closes #11667
2014-02-03 23:27:54 +00:00
|
|
|
};
|
2015-02-27 05:00:43 +00:00
|
|
|
args.push(path.to_str().unwrap().to_string());
|
2014-02-11 21:51:08 +00:00
|
|
|
if props.force_host {
|
2014-09-17 19:56:31 +00:00
|
|
|
args.extend(split_maybe_args(&config.host_rustcflags).into_iter());
|
2014-02-11 21:51:08 +00:00
|
|
|
} else {
|
2014-09-17 19:56:31 +00:00
|
|
|
args.extend(split_maybe_args(&config.target_rustcflags).into_iter());
|
2014-02-11 21:51:08 +00:00
|
|
|
}
|
2014-09-17 19:56:31 +00:00
|
|
|
args.extend(split_maybe_args(&props.compile_flags).into_iter());
|
2014-05-15 03:47:24 +00:00
|
|
|
return ProcArgs {
|
2015-02-27 05:00:43 +00:00
|
|
|
prog: config.rustc_path.to_str().unwrap().to_string(),
|
2014-05-15 03:47:24 +00:00
|
|
|
args: args,
|
|
|
|
};
|
2011-07-31 04:11:14 +00:00
|
|
|
}
|
|
|
|
|
2015-02-27 05:00:43 +00:00
|
|
|
fn make_lib_name(config: &Config, auxfile: &Path, testfile: &Path) -> PathBuf {
|
2012-02-28 05:23:49 +00:00
|
|
|
// what we return here is not particularly important, as it
|
|
|
|
// happens; rustc ignores everything except for the directory.
|
2012-04-10 05:41:27 +00:00
|
|
|
let auxname = output_testname(auxfile);
|
2013-10-08 02:16:58 +00:00
|
|
|
aux_output_dir_name(config, testfile).join(&auxname)
|
2012-02-28 05:23:49 +00:00
|
|
|
}
|
|
|
|
|
2015-02-27 05:00:43 +00:00
|
|
|
fn make_exe_name(config: &Config, testfile: &Path) -> PathBuf {
|
2013-09-27 00:21:59 +00:00
|
|
|
let mut f = output_base_name(config, testfile);
|
2015-01-27 20:20:58 +00:00
|
|
|
if !env::consts::EXE_SUFFIX.is_empty() {
|
2015-02-27 05:00:43 +00:00
|
|
|
let mut fname = f.file_name().unwrap().to_os_string();
|
|
|
|
fname.push_os_str(OsStr::from_str(env::consts::EXE_SUFFIX));
|
|
|
|
f.set_file_name(&fname);
|
2013-10-10 05:05:14 +00:00
|
|
|
}
|
2013-09-27 00:21:59 +00:00
|
|
|
f
|
2011-07-31 04:11:14 +00:00
|
|
|
}
|
|
|
|
|
2014-04-16 04:56:39 +00:00
|
|
|
fn make_run_args(config: &Config, props: &TestProps, testfile: &Path) ->
|
2013-01-26 06:51:32 +00:00
|
|
|
ProcArgs {
|
2013-05-12 02:45:28 +00:00
|
|
|
// If we've got another tool to run under (valgrind),
|
|
|
|
// then split apart its command
|
2013-07-03 02:13:00 +00:00
|
|
|
let mut args = split_maybe_args(&config.runtool);
|
2013-09-27 00:21:59 +00:00
|
|
|
let exe_file = make_exe_name(config, testfile);
|
2014-04-19 09:36:00 +00:00
|
|
|
|
2013-09-27 00:21:59 +00:00
|
|
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
2015-02-27 05:00:43 +00:00
|
|
|
args.push(exe_file.to_str().unwrap().to_string());
|
2014-04-19 09:36:00 +00:00
|
|
|
|
|
|
|
// Add the arguments in the run_flags directive
|
2014-09-17 19:56:31 +00:00
|
|
|
args.extend(split_maybe_args(&props.run_flags).into_iter());
|
2014-04-19 09:36:00 +00:00
|
|
|
|
2014-12-30 18:51:18 +00:00
|
|
|
let prog = args.remove(0);
|
2014-05-15 03:47:24 +00:00
|
|
|
return ProcArgs {
|
|
|
|
prog: prog,
|
|
|
|
args: args,
|
|
|
|
};
|
2011-07-31 04:11:14 +00:00
|
|
|
}
|
|
|
|
|
2014-05-22 23:57:53 +00:00
|
|
|
fn split_maybe_args(argstr: &Option<String>) -> Vec<String> {
|
2013-05-12 02:45:28 +00:00
|
|
|
match *argstr {
|
|
|
|
Some(ref s) => {
|
2015-02-02 02:53:25 +00:00
|
|
|
s
|
2014-05-15 03:47:24 +00:00
|
|
|
.split(' ')
|
|
|
|
.filter_map(|s| {
|
2014-12-11 03:46:38 +00:00
|
|
|
if s.chars().all(|c| c.is_whitespace()) {
|
2014-05-15 03:47:24 +00:00
|
|
|
None
|
|
|
|
} else {
|
2014-05-25 10:17:19 +00:00
|
|
|
Some(s.to_string())
|
2014-05-15 03:47:24 +00:00
|
|
|
}
|
|
|
|
}).collect()
|
2013-03-26 03:39:10 +00:00
|
|
|
}
|
2014-03-05 23:28:08 +00:00
|
|
|
None => Vec::new()
|
2011-07-31 04:11:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-22 23:57:53 +00:00
|
|
|
fn program_output(config: &Config, testfile: &Path, lib_path: &str, prog: String,
|
2014-06-11 21:52:38 +00:00
|
|
|
aux_path: Option<&str>, args: Vec<String>,
|
|
|
|
env: Vec<(String, String)>,
|
2014-05-22 23:57:53 +00:00
|
|
|
input: Option<String>) -> ProcRes {
|
2011-07-31 04:11:14 +00:00
|
|
|
let cmdline =
|
2011-08-19 22:16:48 +00:00
|
|
|
{
|
2014-05-15 03:47:24 +00:00
|
|
|
let cmdline = make_cmdline(lib_path,
|
2015-02-02 02:53:25 +00:00
|
|
|
&prog,
|
|
|
|
&args);
|
2014-05-28 03:44:58 +00:00
|
|
|
logv(config, format!("executing {}", cmdline));
|
2011-08-19 22:16:48 +00:00
|
|
|
cmdline
|
|
|
|
};
|
2014-05-15 03:47:24 +00:00
|
|
|
let procsrv::Result {
|
|
|
|
out,
|
|
|
|
err,
|
|
|
|
status
|
|
|
|
} = procsrv::run(lib_path,
|
2015-02-02 02:53:25 +00:00
|
|
|
&prog,
|
2014-06-11 21:52:38 +00:00
|
|
|
aux_path,
|
2015-02-02 02:53:25 +00:00
|
|
|
&args,
|
2014-05-15 03:47:24 +00:00
|
|
|
env,
|
2015-02-02 02:53:25 +00:00
|
|
|
input).expect(&format!("failed to exec `{}`", prog));
|
|
|
|
dump_output(config, testfile, &out, &err);
|
2014-05-15 03:47:24 +00:00
|
|
|
return ProcRes {
|
2015-02-27 05:00:43 +00:00
|
|
|
status: Status::Normal(status),
|
2014-05-15 03:47:24 +00:00
|
|
|
stdout: out,
|
|
|
|
stderr: err,
|
|
|
|
cmdline: cmdline,
|
|
|
|
};
|
2011-07-31 04:11:14 +00:00
|
|
|
}
|
|
|
|
|
2014-05-22 23:57:53 +00:00
|
|
|
fn make_cmdline(libpath: &str, prog: &str, args: &[String]) -> String {
|
2015-02-27 05:00:43 +00:00
|
|
|
use util;
|
2011-07-31 04:11:14 +00:00
|
|
|
|
2015-02-27 05:00:43 +00:00
|
|
|
// Linux and mac don't require adjusting the library search path
|
|
|
|
if cfg!(unix) {
|
|
|
|
format!("{} {}", prog, args.connect(" "))
|
|
|
|
} else {
|
|
|
|
// Build the LD_LIBRARY_PATH variable as it would be seen on the command line
|
|
|
|
// for diagnostic purposes
|
|
|
|
fn lib_path_cmd_prefix(path: &str) -> String {
|
|
|
|
format!("{}=\"{}\"", util::lib_path_env_var(), util::make_new_path(path))
|
|
|
|
}
|
2014-10-05 10:11:17 +00:00
|
|
|
|
2015-02-27 05:00:43 +00:00
|
|
|
format!("{} {} {}", lib_path_cmd_prefix(libpath), prog, args.connect(" "))
|
|
|
|
}
|
2011-07-31 04:11:14 +00:00
|
|
|
}
|
|
|
|
|
2014-04-16 04:56:39 +00:00
|
|
|
fn dump_output(config: &Config, testfile: &Path, out: &str, err: &str) {
|
2013-05-12 02:45:28 +00:00
|
|
|
dump_output_file(config, testfile, out, "out");
|
|
|
|
dump_output_file(config, testfile, err, "err");
|
2011-07-31 04:11:14 +00:00
|
|
|
maybe_dump_to_stdout(config, out, err);
|
|
|
|
}
|
|
|
|
|
2014-04-16 04:56:39 +00:00
|
|
|
fn dump_output_file(config: &Config, testfile: &Path,
|
2013-05-12 02:45:28 +00:00
|
|
|
out: &str, extension: &str) {
|
2011-07-31 04:11:14 +00:00
|
|
|
let outfile = make_out_name(config, testfile, extension);
|
2015-02-27 05:00:43 +00:00
|
|
|
File::create(&outfile).unwrap().write_all(out.as_bytes()).unwrap();
|
2011-07-31 04:11:14 +00:00
|
|
|
}
|
|
|
|
|
2015-02-27 05:00:43 +00:00
|
|
|
fn make_out_name(config: &Config, testfile: &Path, extension: &str) -> PathBuf {
|
2013-10-06 02:49:32 +00:00
|
|
|
output_base_name(config, testfile).with_extension(extension)
|
2011-07-31 04:11:14 +00:00
|
|
|
}
|
|
|
|
|
2015-02-27 05:00:43 +00:00
|
|
|
fn aux_output_dir_name(config: &Config, testfile: &Path) -> PathBuf {
|
2014-09-17 19:56:31 +00:00
|
|
|
let f = output_base_name(config, testfile);
|
2015-02-27 05:00:43 +00:00
|
|
|
let mut fname = f.file_name().unwrap().to_os_string();
|
|
|
|
fname.push_os_str(OsStr::from_str("libaux"));
|
|
|
|
f.with_file_name(&fname)
|
2012-04-10 05:41:27 +00:00
|
|
|
}
|
|
|
|
|
2015-02-27 05:00:43 +00:00
|
|
|
fn output_testname(testfile: &Path) -> PathBuf {
|
|
|
|
PathBuf::new(testfile.file_stem().unwrap())
|
2012-04-10 05:41:27 +00:00
|
|
|
}
|
|
|
|
|
2015-02-27 05:00:43 +00:00
|
|
|
fn output_base_name(config: &Config, testfile: &Path) -> PathBuf {
|
2012-08-24 22:28:43 +00:00
|
|
|
config.build_base
|
2013-10-08 02:16:58 +00:00
|
|
|
.join(&output_testname(testfile))
|
2015-02-02 02:53:25 +00:00
|
|
|
.with_extension(&config.stage_id)
|
2011-07-31 04:11:14 +00:00
|
|
|
}
|
|
|
|
|
2014-04-16 04:56:39 +00:00
|
|
|
fn maybe_dump_to_stdout(config: &Config, out: &str, err: &str) {
|
2011-07-31 04:11:14 +00:00
|
|
|
if config.verbose {
|
2013-10-14 01:48:47 +00:00
|
|
|
println!("------{}------------------------------", "stdout");
|
|
|
|
println!("{}", out);
|
|
|
|
println!("------{}------------------------------", "stderr");
|
|
|
|
println!("{}", err);
|
|
|
|
println!("------------------------------------------");
|
2011-07-31 04:11:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-25 05:35:54 +00:00
|
|
|
fn error(err: &str) { println!("\nerror: {}", err); }
|
2011-07-31 04:11:14 +00:00
|
|
|
|
2014-10-09 19:17:22 +00:00
|
|
|
fn fatal(err: &str) -> ! { error(err); panic!(); }
|
2011-07-31 04:11:14 +00:00
|
|
|
|
2014-06-25 05:35:54 +00:00
|
|
|
fn fatal_proc_rec(err: &str, proc_res: &ProcRes) -> ! {
|
2013-10-14 01:48:47 +00:00
|
|
|
print!("\n\
|
2013-09-29 20:18:51 +00:00
|
|
|
error: {}\n\
|
2014-04-23 16:38:46 +00:00
|
|
|
status: {}\n\
|
2013-09-29 20:18:51 +00:00
|
|
|
command: {}\n\
|
2011-07-31 04:11:14 +00:00
|
|
|
stdout:\n\
|
|
|
|
------------------------------------------\n\
|
2013-09-29 20:18:51 +00:00
|
|
|
{}\n\
|
2011-07-31 04:11:14 +00:00
|
|
|
------------------------------------------\n\
|
|
|
|
stderr:\n\
|
|
|
|
------------------------------------------\n\
|
2013-09-29 20:18:51 +00:00
|
|
|
{}\n\
|
2011-07-31 04:11:14 +00:00
|
|
|
------------------------------------------\n\
|
|
|
|
\n",
|
2014-04-23 16:38:46 +00:00
|
|
|
err, proc_res.status, proc_res.cmdline, proc_res.stdout,
|
|
|
|
proc_res.stderr);
|
2014-10-09 19:17:22 +00:00
|
|
|
panic!();
|
2011-07-31 04:11:14 +00:00
|
|
|
}
|
2013-05-04 01:35:07 +00:00
|
|
|
|
2014-05-15 03:47:24 +00:00
|
|
|
fn _arm_exec_compiled_test(config: &Config,
|
|
|
|
props: &TestProps,
|
|
|
|
testfile: &Path,
|
2014-05-22 23:57:53 +00:00
|
|
|
env: Vec<(String, String)>)
|
2014-05-15 03:47:24 +00:00
|
|
|
-> ProcRes {
|
2013-05-04 01:35:07 +00:00
|
|
|
let args = make_run_args(config, props, testfile);
|
2014-05-15 03:47:24 +00:00
|
|
|
let cmdline = make_cmdline("",
|
2015-02-02 02:53:25 +00:00
|
|
|
&args.prog,
|
|
|
|
&args.args);
|
2013-05-04 01:35:07 +00:00
|
|
|
|
|
|
|
// get bare program string
|
2014-05-22 23:57:53 +00:00
|
|
|
let mut tvec: Vec<String> = args.prog
|
2014-05-15 03:47:24 +00:00
|
|
|
.split('/')
|
2014-05-25 10:17:19 +00:00
|
|
|
.map(|ts| ts.to_string())
|
2014-05-15 03:47:24 +00:00
|
|
|
.collect();
|
2013-12-23 15:20:52 +00:00
|
|
|
let prog_short = tvec.pop().unwrap();
|
2013-05-04 01:35:07 +00:00
|
|
|
|
|
|
|
// copy to target
|
2014-05-15 03:47:24 +00:00
|
|
|
let copy_result = procsrv::run("",
|
2015-02-02 02:53:25 +00:00
|
|
|
&config.adb_path,
|
2014-06-11 21:52:38 +00:00
|
|
|
None,
|
2014-11-17 08:39:01 +00:00
|
|
|
&[
|
2014-05-25 10:17:19 +00:00
|
|
|
"push".to_string(),
|
2014-05-15 03:47:24 +00:00
|
|
|
args.prog.clone(),
|
|
|
|
config.adb_test_dir.clone()
|
|
|
|
],
|
2014-05-25 10:17:19 +00:00
|
|
|
vec!(("".to_string(), "".to_string())),
|
|
|
|
Some("".to_string()))
|
2015-02-02 02:53:25 +00:00
|
|
|
.expect(&format!("failed to exec `{}`", config.adb_path));
|
2013-05-29 07:04:47 +00:00
|
|
|
|
|
|
|
if config.verbose {
|
2013-10-14 01:48:47 +00:00
|
|
|
println!("push ({}) {} {} {}",
|
2014-05-15 03:47:24 +00:00
|
|
|
config.target,
|
|
|
|
args.prog,
|
|
|
|
copy_result.out,
|
|
|
|
copy_result.err);
|
2013-05-29 07:04:47 +00:00
|
|
|
}
|
|
|
|
|
2014-05-28 03:44:58 +00:00
|
|
|
logv(config, format!("executing ({}) {}", config.target, cmdline));
|
2013-05-29 07:04:47 +00:00
|
|
|
|
2014-03-05 23:28:08 +00:00
|
|
|
let mut runargs = Vec::new();
|
2013-05-29 07:04:47 +00:00
|
|
|
|
2013-06-01 08:27:30 +00:00
|
|
|
// run test via adb_run_wrapper
|
2014-05-25 10:17:19 +00:00
|
|
|
runargs.push("shell".to_string());
|
2015-02-01 01:03:04 +00:00
|
|
|
for (key, val) in env {
|
2014-05-28 03:44:58 +00:00
|
|
|
runargs.push(format!("{}={}", key, val));
|
2013-08-28 12:44:55 +00:00
|
|
|
}
|
2015-02-02 08:42:23 +00:00
|
|
|
runargs.push(format!("{}/../adb_run_wrapper.sh", config.adb_test_dir));
|
2014-05-28 03:44:58 +00:00
|
|
|
runargs.push(format!("{}", config.adb_test_dir));
|
|
|
|
runargs.push(format!("{}", prog_short));
|
2013-05-29 07:04:47 +00:00
|
|
|
|
2015-01-31 17:20:46 +00:00
|
|
|
for tv in &args.args {
|
2014-05-25 10:17:19 +00:00
|
|
|
runargs.push(tv.to_string());
|
2013-06-01 08:27:30 +00:00
|
|
|
}
|
2014-03-05 23:28:08 +00:00
|
|
|
procsrv::run("",
|
2015-02-02 02:53:25 +00:00
|
|
|
&config.adb_path,
|
2014-06-11 21:52:38 +00:00
|
|
|
None,
|
2015-02-02 02:53:25 +00:00
|
|
|
&runargs,
|
2014-05-25 10:17:19 +00:00
|
|
|
vec!(("".to_string(), "".to_string())), Some("".to_string()))
|
2015-02-02 02:53:25 +00:00
|
|
|
.expect(&format!("failed to exec `{}`", config.adb_path));
|
2013-05-29 07:04:47 +00:00
|
|
|
|
2013-06-01 08:27:30 +00:00
|
|
|
// get exitcode of result
|
2014-03-05 23:28:08 +00:00
|
|
|
runargs = Vec::new();
|
2014-05-25 10:17:19 +00:00
|
|
|
runargs.push("shell".to_string());
|
|
|
|
runargs.push("cat".to_string());
|
2014-05-28 03:44:58 +00:00
|
|
|
runargs.push(format!("{}/{}.exitcode", config.adb_test_dir, prog_short));
|
2013-06-01 08:27:30 +00:00
|
|
|
|
|
|
|
let procsrv::Result{ out: exitcode_out, err: _, status: _ } =
|
2014-05-15 03:47:24 +00:00
|
|
|
procsrv::run("",
|
2015-02-02 02:53:25 +00:00
|
|
|
&config.adb_path,
|
2014-06-11 21:52:38 +00:00
|
|
|
None,
|
2015-02-02 02:53:25 +00:00
|
|
|
&runargs,
|
2014-05-25 10:17:19 +00:00
|
|
|
vec!(("".to_string(), "".to_string())),
|
|
|
|
Some("".to_string()))
|
2015-02-02 02:53:25 +00:00
|
|
|
.expect(&format!("failed to exec `{}`", config.adb_path));
|
2013-06-01 08:27:30 +00:00
|
|
|
|
2015-02-27 05:00:43 +00:00
|
|
|
let mut exitcode: i32 = 0;
|
2015-01-27 02:21:15 +00:00
|
|
|
for c in exitcode_out.chars() {
|
2014-10-09 00:15:27 +00:00
|
|
|
if !c.is_numeric() { break; }
|
2013-06-01 08:27:30 +00:00
|
|
|
exitcode = exitcode * 10 + match c {
|
2015-02-27 05:00:43 +00:00
|
|
|
'0' ... '9' => c as i32 - ('0' as i32),
|
2013-06-01 08:27:30 +00:00
|
|
|
_ => 101,
|
2013-05-29 07:04:47 +00:00
|
|
|
}
|
2013-06-01 08:27:30 +00:00
|
|
|
}
|
2013-05-29 07:04:47 +00:00
|
|
|
|
|
|
|
// get stdout of result
|
2014-03-05 23:28:08 +00:00
|
|
|
runargs = Vec::new();
|
2014-05-25 10:17:19 +00:00
|
|
|
runargs.push("shell".to_string());
|
|
|
|
runargs.push("cat".to_string());
|
2014-05-28 03:44:58 +00:00
|
|
|
runargs.push(format!("{}/{}.stdout", config.adb_test_dir, prog_short));
|
2013-05-29 07:04:47 +00:00
|
|
|
|
2013-06-01 08:27:30 +00:00
|
|
|
let procsrv::Result{ out: stdout_out, err: _, status: _ } =
|
2014-03-05 23:28:08 +00:00
|
|
|
procsrv::run("",
|
2015-02-02 02:53:25 +00:00
|
|
|
&config.adb_path,
|
2014-06-11 21:52:38 +00:00
|
|
|
None,
|
2015-02-02 02:53:25 +00:00
|
|
|
&runargs,
|
2014-05-25 10:17:19 +00:00
|
|
|
vec!(("".to_string(), "".to_string())),
|
|
|
|
Some("".to_string()))
|
2015-02-02 02:53:25 +00:00
|
|
|
.expect(&format!("failed to exec `{}`", config.adb_path));
|
2013-05-29 07:04:47 +00:00
|
|
|
|
|
|
|
// get stderr of result
|
2014-03-05 23:28:08 +00:00
|
|
|
runargs = Vec::new();
|
2014-05-25 10:17:19 +00:00
|
|
|
runargs.push("shell".to_string());
|
|
|
|
runargs.push("cat".to_string());
|
2014-05-28 03:44:58 +00:00
|
|
|
runargs.push(format!("{}/{}.stderr", config.adb_test_dir, prog_short));
|
2013-05-29 07:04:47 +00:00
|
|
|
|
2013-06-01 08:27:30 +00:00
|
|
|
let procsrv::Result{ out: stderr_out, err: _, status: _ } =
|
2014-03-05 23:28:08 +00:00
|
|
|
procsrv::run("",
|
2015-02-02 02:53:25 +00:00
|
|
|
&config.adb_path,
|
2014-06-11 21:52:38 +00:00
|
|
|
None,
|
2015-02-02 02:53:25 +00:00
|
|
|
&runargs,
|
2014-05-25 10:17:19 +00:00
|
|
|
vec!(("".to_string(), "".to_string())),
|
|
|
|
Some("".to_string()))
|
2015-02-02 02:53:25 +00:00
|
|
|
.expect(&format!("failed to exec `{}`", config.adb_path));
|
2013-05-29 07:04:47 +00:00
|
|
|
|
2014-05-15 03:47:24 +00:00
|
|
|
dump_output(config,
|
|
|
|
testfile,
|
2015-02-02 02:53:25 +00:00
|
|
|
&stdout_out,
|
|
|
|
&stderr_out);
|
2013-05-29 07:04:47 +00:00
|
|
|
|
2013-11-12 01:37:14 +00:00
|
|
|
ProcRes {
|
2015-02-27 05:00:43 +00:00
|
|
|
status: Status::Parsed(exitcode),
|
2013-11-12 01:37:14 +00:00
|
|
|
stdout: stdout_out,
|
|
|
|
stderr: stderr_out,
|
|
|
|
cmdline: cmdline
|
|
|
|
}
|
2013-05-29 07:04:47 +00:00
|
|
|
}
|
|
|
|
|
2014-04-16 04:56:39 +00:00
|
|
|
fn _arm_push_aux_shared_library(config: &Config, testfile: &Path) {
|
2013-09-27 00:21:59 +00:00
|
|
|
let tdir = aux_output_dir_name(config, testfile);
|
2013-05-04 01:35:07 +00:00
|
|
|
|
2015-02-27 05:00:43 +00:00
|
|
|
let dirs = fs::read_dir(&tdir).unwrap();
|
|
|
|
for file in dirs {
|
|
|
|
let file = file.unwrap().path();
|
|
|
|
if file.extension().and_then(|s| s.to_str()) == Some("so") {
|
2013-09-27 00:21:59 +00:00
|
|
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
2014-05-15 03:47:24 +00:00
|
|
|
let copy_result = procsrv::run("",
|
2015-02-02 02:53:25 +00:00
|
|
|
&config.adb_path,
|
2014-06-11 21:52:38 +00:00
|
|
|
None,
|
2014-11-17 08:39:01 +00:00
|
|
|
&[
|
2014-05-25 10:17:19 +00:00
|
|
|
"push".to_string(),
|
2015-02-27 05:00:43 +00:00
|
|
|
file.to_str()
|
2014-05-15 03:47:24 +00:00
|
|
|
.unwrap()
|
2014-05-25 10:17:19 +00:00
|
|
|
.to_string(),
|
2015-02-02 08:42:23 +00:00
|
|
|
config.adb_test_dir.to_string(),
|
2014-05-15 03:47:24 +00:00
|
|
|
],
|
2014-05-25 10:17:19 +00:00
|
|
|
vec!(("".to_string(),
|
|
|
|
"".to_string())),
|
|
|
|
Some("".to_string()))
|
2015-02-02 02:53:25 +00:00
|
|
|
.expect(&format!("failed to exec `{}`", config.adb_path));
|
2013-05-04 01:35:07 +00:00
|
|
|
|
|
|
|
if config.verbose {
|
2014-12-20 08:09:35 +00:00
|
|
|
println!("push ({}) {:?} {} {}",
|
2013-09-27 00:21:59 +00:00
|
|
|
config.target, file.display(),
|
2013-10-14 01:48:47 +00:00
|
|
|
copy_result.out, copy_result.err);
|
2013-05-04 01:35:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-07-06 07:44:40 +00:00
|
|
|
|
|
|
|
// codegen tests (vs. clang)
|
|
|
|
|
2015-02-27 05:00:43 +00:00
|
|
|
fn append_suffix_to_stem(p: &Path, suffix: &str) -> PathBuf {
|
2013-07-06 07:44:40 +00:00
|
|
|
if suffix.len() == 0 {
|
2015-02-27 05:00:43 +00:00
|
|
|
p.to_path_buf()
|
2013-07-06 07:44:40 +00:00
|
|
|
} else {
|
2015-02-27 05:00:43 +00:00
|
|
|
let mut stem = p.file_stem().unwrap().to_os_string();
|
|
|
|
stem.push_os_str(OsStr::from_str("-"));
|
|
|
|
stem.push_os_str(OsStr::from_str(suffix));
|
|
|
|
p.with_file_name(&stem)
|
2013-07-06 07:44:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-16 04:56:39 +00:00
|
|
|
fn compile_test_and_save_bitcode(config: &Config, props: &TestProps,
|
2013-07-06 07:44:40 +00:00
|
|
|
testfile: &Path) -> ProcRes {
|
2013-09-27 00:21:59 +00:00
|
|
|
let aux_dir = aux_output_dir_name(config, testfile);
|
|
|
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
2014-09-17 19:56:31 +00:00
|
|
|
let mut link_args = vec!("-L".to_string(),
|
2015-02-27 05:00:43 +00:00
|
|
|
aux_dir.to_str().unwrap().to_string());
|
2014-12-16 00:03:39 +00:00
|
|
|
let llvm_args = vec!("--emit=llvm-bc,obj".to_string(),
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
"--crate-type=lib".to_string());
|
2014-09-17 19:56:31 +00:00
|
|
|
link_args.extend(llvm_args.into_iter());
|
2014-03-05 23:28:08 +00:00
|
|
|
let args = make_compile_args(config,
|
|
|
|
props,
|
2014-09-17 19:56:31 +00:00
|
|
|
link_args,
|
2014-11-21 18:50:44 +00:00
|
|
|
|a, b| TargetLocation::ThisDirectory(
|
2015-02-27 05:00:43 +00:00
|
|
|
output_base_name(a, b).parent()
|
|
|
|
.unwrap().to_path_buf()),
|
run optimization and codegen on worker threads
Refactor the code in `llvm::back` that invokes LLVM optimization and codegen
passes so that it can be called from worker threads. (Previously, it used
`&Session` extensively, and `Session` is not `Share`.) The new code can handle
multiple compilation units, by compiling each unit to `crate.0.o`, `crate.1.o`,
etc., and linking together all the `crate.N.o` files into a single `crate.o`
using `ld -r`. The later linking steps can then be run unchanged.
The new code preserves the behavior of `--emit`/`-o` when building a single
compilation unit. With multiple compilation units, the `--emit=asm/ir/bc`
options produce multiple files, so combinations like `--emit=ir -o foo.ll` will
not actually produce `foo.ll` (they instead produce several `foo.N.ll` files).
The new code supports `-Z lto` only when using a single compilation unit.
Compiling with multiple compilation units and `-Z lto` will produce an error.
(I can't think of any good reason to do such a thing.) Linking with `-Z lto`
against a library that was built as multiple compilation units will also fail,
because the rlib does not contain a `crate.bytecode.deflate` file. This could
be supported in the future by linking together the `crate.N.bc` files produced
when compiling the library into a single `crate.bc`, or by making the LTO code
support multiple `crate.N.bytecode.deflate` files.
2014-07-17 17:52:52 +00:00
|
|
|
testfile);
|
2013-07-06 07:44:40 +00:00
|
|
|
compose_and_run_compiler(config, props, testfile, args, None)
|
|
|
|
}
|
|
|
|
|
2014-04-16 04:56:39 +00:00
|
|
|
fn compile_cc_with_clang_and_save_bitcode(config: &Config, _props: &TestProps,
|
2013-07-06 07:44:40 +00:00
|
|
|
testfile: &Path) -> ProcRes {
|
2013-10-06 02:49:32 +00:00
|
|
|
let bitcodefile = output_base_name(config, testfile).with_extension("bc");
|
2013-07-06 07:44:40 +00:00
|
|
|
let bitcodefile = append_suffix_to_stem(&bitcodefile, "clang");
|
2013-10-06 02:49:32 +00:00
|
|
|
let testcc = testfile.with_extension("cc");
|
2014-02-15 21:15:03 +00:00
|
|
|
let proc_args = ProcArgs {
|
2013-09-27 00:21:59 +00:00
|
|
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
2015-02-27 05:00:43 +00:00
|
|
|
prog: config.clang_path.as_ref().unwrap().to_str().unwrap().to_string(),
|
2014-05-25 10:17:19 +00:00
|
|
|
args: vec!("-c".to_string(),
|
|
|
|
"-emit-llvm".to_string(),
|
|
|
|
"-o".to_string(),
|
2015-02-27 05:00:43 +00:00
|
|
|
bitcodefile.to_str().unwrap().to_string(),
|
|
|
|
testcc.to_str().unwrap().to_string())
|
2013-07-06 07:44:40 +00:00
|
|
|
};
|
2014-06-11 21:52:38 +00:00
|
|
|
compose_and_run(config, testfile, proc_args, Vec::new(), "", None, None)
|
2013-07-06 07:44:40 +00:00
|
|
|
}
|
|
|
|
|
2014-04-16 04:56:39 +00:00
|
|
|
fn extract_function_from_bitcode(config: &Config, _props: &TestProps,
|
2013-07-06 07:44:40 +00:00
|
|
|
fname: &str, testfile: &Path,
|
|
|
|
suffix: &str) -> ProcRes {
|
2013-10-06 02:49:32 +00:00
|
|
|
let bitcodefile = output_base_name(config, testfile).with_extension("bc");
|
2013-07-06 07:44:40 +00:00
|
|
|
let bitcodefile = append_suffix_to_stem(&bitcodefile, suffix);
|
|
|
|
let extracted_bc = append_suffix_to_stem(&bitcodefile, "extract");
|
2014-08-19 00:52:38 +00:00
|
|
|
let prog = config.llvm_bin_path.as_ref().unwrap().join("llvm-extract");
|
2014-02-15 21:15:03 +00:00
|
|
|
let proc_args = ProcArgs {
|
2013-09-27 00:21:59 +00:00
|
|
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
2015-02-27 05:00:43 +00:00
|
|
|
prog: prog.to_str().unwrap().to_string(),
|
2014-05-28 03:44:58 +00:00
|
|
|
args: vec!(format!("-func={}", fname),
|
2015-02-27 05:00:43 +00:00
|
|
|
format!("-o={}", extracted_bc.to_str().unwrap()),
|
|
|
|
bitcodefile.to_str().unwrap().to_string())
|
2013-07-06 07:44:40 +00:00
|
|
|
};
|
2014-06-11 21:52:38 +00:00
|
|
|
compose_and_run(config, testfile, proc_args, Vec::new(), "", None, None)
|
2013-07-06 07:44:40 +00:00
|
|
|
}
|
|
|
|
|
2014-04-16 04:56:39 +00:00
|
|
|
fn disassemble_extract(config: &Config, _props: &TestProps,
|
2013-07-06 07:44:40 +00:00
|
|
|
testfile: &Path, suffix: &str) -> ProcRes {
|
2013-10-06 02:49:32 +00:00
|
|
|
let bitcodefile = output_base_name(config, testfile).with_extension("bc");
|
2013-07-06 07:44:40 +00:00
|
|
|
let bitcodefile = append_suffix_to_stem(&bitcodefile, suffix);
|
|
|
|
let extracted_bc = append_suffix_to_stem(&bitcodefile, "extract");
|
2013-10-06 02:49:32 +00:00
|
|
|
let extracted_ll = extracted_bc.with_extension("ll");
|
2014-08-19 00:52:38 +00:00
|
|
|
let prog = config.llvm_bin_path.as_ref().unwrap().join("llvm-dis");
|
2014-02-15 21:15:03 +00:00
|
|
|
let proc_args = ProcArgs {
|
2013-09-27 00:21:59 +00:00
|
|
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
2015-02-27 05:00:43 +00:00
|
|
|
prog: prog.to_str().unwrap().to_string(),
|
|
|
|
args: vec!(format!("-o={}", extracted_ll.to_str().unwrap()),
|
|
|
|
extracted_bc.to_str().unwrap().to_string())
|
2013-07-06 07:44:40 +00:00
|
|
|
};
|
2014-06-11 21:52:38 +00:00
|
|
|
compose_and_run(config, testfile, proc_args, Vec::new(), "", None, None)
|
2013-07-06 07:44:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-16 01:51:20 +00:00
|
|
|
fn count_extracted_lines(p: &Path) -> uint {
|
2015-02-27 05:00:43 +00:00
|
|
|
let mut x = Vec::new();
|
|
|
|
File::open(&p.with_extension("ll")).unwrap().read_to_end(&mut x).unwrap();
|
2015-02-02 02:53:25 +00:00
|
|
|
let x = str::from_utf8(&x).unwrap();
|
2014-06-06 06:18:51 +00:00
|
|
|
x.lines().count()
|
2013-07-16 01:51:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-16 04:56:39 +00:00
|
|
|
fn run_codegen_test(config: &Config, props: &TestProps,
|
2013-07-16 01:51:20 +00:00
|
|
|
testfile: &Path, mm: &mut MetricMap) {
|
2013-07-06 07:44:40 +00:00
|
|
|
|
|
|
|
if config.llvm_bin_path.is_none() {
|
2014-06-25 05:35:54 +00:00
|
|
|
fatal("missing --llvm-bin-path");
|
2013-07-06 07:44:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if config.clang_path.is_none() {
|
2014-06-25 05:35:54 +00:00
|
|
|
fatal("missing --clang-path");
|
2013-07-06 07:44:40 +00:00
|
|
|
}
|
|
|
|
|
2014-02-15 21:15:03 +00:00
|
|
|
let mut proc_res = compile_test_and_save_bitcode(config, props, testfile);
|
|
|
|
if !proc_res.status.success() {
|
2014-06-25 05:35:54 +00:00
|
|
|
fatal_proc_rec("compilation failed!", &proc_res);
|
2013-07-06 07:44:40 +00:00
|
|
|
}
|
|
|
|
|
2014-02-15 21:15:03 +00:00
|
|
|
proc_res = extract_function_from_bitcode(config, props, "test", testfile, "");
|
|
|
|
if !proc_res.status.success() {
|
2014-06-25 05:35:54 +00:00
|
|
|
fatal_proc_rec("extracting 'test' function failed",
|
2014-05-15 03:47:24 +00:00
|
|
|
&proc_res);
|
2013-07-06 07:44:40 +00:00
|
|
|
}
|
|
|
|
|
2014-02-15 21:15:03 +00:00
|
|
|
proc_res = disassemble_extract(config, props, testfile, "");
|
|
|
|
if !proc_res.status.success() {
|
2014-06-25 05:35:54 +00:00
|
|
|
fatal_proc_rec("disassembling extract failed", &proc_res);
|
2013-07-06 07:44:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-02-15 21:15:03 +00:00
|
|
|
let mut proc_res = compile_cc_with_clang_and_save_bitcode(config, props, testfile);
|
|
|
|
if !proc_res.status.success() {
|
2014-06-25 05:35:54 +00:00
|
|
|
fatal_proc_rec("compilation failed!", &proc_res);
|
2013-07-06 07:44:40 +00:00
|
|
|
}
|
|
|
|
|
2014-02-15 21:15:03 +00:00
|
|
|
proc_res = extract_function_from_bitcode(config, props, "test", testfile, "clang");
|
|
|
|
if !proc_res.status.success() {
|
2014-06-25 05:35:54 +00:00
|
|
|
fatal_proc_rec("extracting 'test' function failed",
|
2014-05-15 03:47:24 +00:00
|
|
|
&proc_res);
|
2013-07-06 07:44:40 +00:00
|
|
|
}
|
|
|
|
|
2014-02-15 21:15:03 +00:00
|
|
|
proc_res = disassemble_extract(config, props, testfile, "clang");
|
|
|
|
if !proc_res.status.success() {
|
2014-06-25 05:35:54 +00:00
|
|
|
fatal_proc_rec("disassembling extract failed", &proc_res);
|
2013-07-06 07:44:40 +00:00
|
|
|
}
|
|
|
|
|
2013-07-16 01:51:20 +00:00
|
|
|
let base = output_base_name(config, testfile);
|
|
|
|
let base_extract = append_suffix_to_stem(&base, "extract");
|
|
|
|
|
|
|
|
let base_clang = append_suffix_to_stem(&base, "clang");
|
|
|
|
let base_clang_extract = append_suffix_to_stem(&base_clang, "extract");
|
2013-07-06 07:44:40 +00:00
|
|
|
|
2013-07-16 01:51:20 +00:00
|
|
|
let base_lines = count_extracted_lines(&base_extract);
|
|
|
|
let clang_lines = count_extracted_lines(&base_clang_extract);
|
2013-07-06 07:44:40 +00:00
|
|
|
|
2013-07-16 01:51:20 +00:00
|
|
|
mm.insert_metric("clang-codegen-ratio",
|
|
|
|
(base_lines as f64) / (clang_lines as f64),
|
|
|
|
0.001);
|
2013-07-06 07:44:40 +00:00
|
|
|
}
|