diff options
| author | bors <bors@rust-lang.org> | 2014-08-30 04:01:24 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-08-30 04:01:24 +0000 |
| commit | c8e86e977f5f95bd2f533c12ebf8107fb6f21a0f (patch) | |
| tree | 12e10399d982fca7a5633917f55bc0a2da3c899c /src/compiletest | |
| parent | 5419b2ca2c27b4745fa1f2773719350420542c76 (diff) | |
| parent | e72e4dfc74ca65d6b3e0d821b94a34764ab2c63d (diff) | |
| download | rust-c8e86e977f5f95bd2f533c12ebf8107fb6f21a0f.tar.gz rust-c8e86e977f5f95bd2f533c12ebf8107fb6f21a0f.zip | |
auto merge of #16322 : michaelwoerister/rust/gdb-pretty, r=alexcrichton
Also extends the autotest framework to let a test case choose if pretty printing should be enabled.
Diffstat (limited to 'src/compiletest')
| -rw-r--r-- | src/compiletest/common.rs | 3 | ||||
| -rw-r--r-- | src/compiletest/compiletest.rs | 25 | ||||
| -rw-r--r-- | src/compiletest/header.rs | 69 | ||||
| -rw-r--r-- | src/compiletest/runtest.rs | 114 |
4 files changed, 183 insertions, 28 deletions
diff --git a/src/compiletest/common.rs b/src/compiletest/common.rs index ba201a4a633..afe2d071461 100644 --- a/src/compiletest/common.rs +++ b/src/compiletest/common.rs @@ -130,6 +130,9 @@ pub struct Config { // Host triple for the compiler being invoked pub host: String, + // Version of GDB + pub gdb_version: Option<String>, + // Path to the android tools pub android_cross_path: Path, diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index 583d9249b35..6c6cd6f610f 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -81,6 +81,7 @@ pub fn parse_config(args: Vec<String> ) -> Config { optflag("", "jit", "run tests under the JIT"), optopt("", "target", "the target to build for", "TARGET"), optopt("", "host", "the host to build for", "HOST"), + optopt("", "gdb-version", "the version of GDB used", "MAJOR.MINOR"), optopt("", "android-cross-path", "Android NDK standalone path", "PATH"), optopt("", "adb-path", "path to the android debugger", "PATH"), optopt("", "adb-test-dir", "path to tests for the android debugger", "PATH"), @@ -157,6 +158,7 @@ pub fn parse_config(args: Vec<String> ) -> Config { jit: matches.opt_present("jit"), target: opt_str2(matches.opt_str("target")), host: opt_str2(matches.opt_str("host")), + gdb_version: extract_gdb_version(matches.opt_str("gdb-version")), android_cross_path: opt_path(matches, "android-cross-path"), adb_path: opt_str2(matches.opt_str("adb-path")), adb_test_dir: opt_str2(matches.opt_str("adb-test-dir")), @@ -376,3 +378,26 @@ pub fn make_metrics_test_closure(config: &Config, testfile: &Path) -> test::Test runtest::run_metrics(config, testfile, mm) }) } + +fn extract_gdb_version(full_version_line: Option<String>) -> Option<String> { + match full_version_line { + Some(ref full_version_line) + if full_version_line.as_slice().trim().len() > 0 => { + let full_version_line = full_version_line.as_slice().trim(); + + let re = Regex::new(r"(^|[^0-9])([0-9]\.[0-9])([^0-9]|$)").unwrap(); + + match re.captures(full_version_line) { + Some(captures) => { + Some(captures.at(2).to_string()) + } + None => { + println!("Could not extract GDB version from line '{}'", + full_version_line); + None + } + } + }, + _ => None + } +} \ No newline at end of file diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index f6cd217b580..9ad2582dec8 100644 --- a/src/compiletest/header.rs +++ b/src/compiletest/header.rs @@ -12,6 +12,8 @@ use common::Config; use common; use util; +use std::from_str::FromStr; + pub struct TestProps { // Lines that should be expected, in order, on standard out pub error_patterns: Vec<String> , @@ -142,23 +144,42 @@ pub fn is_test_ignored(config: &Config, testfile: &Path) -> bool { format!("ignore-{}", config.stage_id.as_slice().split('-').next().unwrap()) } + fn ignore_gdb(config: &Config, line: &str) -> bool { + if config.mode != common::DebugInfoGdb { + return false; + } - let val = iter_header(testfile, |ln| { - if parse_name_directive(ln, "ignore-test") { - false - } else if parse_name_directive(ln, ignore_target(config).as_slice()) { - false - } else if parse_name_directive(ln, ignore_stage(config).as_slice()) { - false - } else if config.mode == common::Pretty && - parse_name_directive(ln, "ignore-pretty") { - false - } else if config.target != config.host && - parse_name_directive(ln, "ignore-cross-compile") { - false - } else { - true + if parse_name_directive(line, "ignore-gdb") { + return true; } + + match config.gdb_version { + Some(ref actual_version) => { + if line.contains("min-gdb-version") { + let min_version = line.trim() + .split(' ') + .last() + .expect("Malformed GDB version directive"); + // Ignore if actual version is smaller the minimum required + // version + gdb_version_to_int(actual_version.as_slice()) < + gdb_version_to_int(min_version.as_slice()) + } else { + false + } + } + None => false + } + } + + let val = iter_header(testfile, |ln| { + !parse_name_directive(ln, "ignore-test") && + !parse_name_directive(ln, ignore_target(config).as_slice()) && + !parse_name_directive(ln, ignore_stage(config).as_slice()) && + !(config.mode == common::Pretty && parse_name_directive(ln, "ignore-pretty")) && + !(config.target != config.host && parse_name_directive(ln, "ignore-cross-compile")) && + !ignore_gdb(config, ln) && + !(config.mode == common::DebugInfoLldb && parse_name_directive(ln, "ignore-lldb")) }); !val @@ -278,3 +299,21 @@ pub fn parse_name_value_directive(line: &str, directive: &str) None => None } } + +pub fn gdb_version_to_int(version_string: &str) -> int { + let error_string = format!( + "Encountered GDB version string with unexpected format: {}", + version_string); + let error_string = error_string.as_slice(); + + let components: Vec<&str> = version_string.trim().split('.').collect(); + + if components.len() != 2 { + fail!("{}", error_string); + } + + let major: int = FromStr::from_str(components[0]).expect(error_string); + let minor: int = FromStr::from_str(components[1]).expect(error_string); + + return major * 1000 + minor; +} diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 7a0245164ec..ee787a5f0a9 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -323,7 +323,12 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) { }; let config = &mut config; - let DebuggerCommands { commands, check_lines, .. } = parse_debugger_commands(testfile, "gdb"); + let DebuggerCommands { + commands, + check_lines, + use_gdb_pretty_printer, + .. + } = parse_debugger_commands(testfile, "gdb"); let mut cmds = commands.connect("\n"); // compile test file (it should have 'compile-flags:-g' in the header) @@ -334,7 +339,6 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) { let exe_file = make_exe_name(config, testfile); - let mut proc_args; let debugger_run_result; match config.target.as_slice() { "arm-linux-androideabi" => { @@ -454,18 +458,65 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) { } _=> { + 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"); + let rust_pp_module_abs_path = rust_src_root.join(rust_pp_module_rel_path) + .as_str() + .unwrap() + .to_string(); // write debugger script - let script_str = [ - "set charset UTF-8".to_string(), - cmds, - "quit\n".to_string() - ].connect("\n"); + 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) => { + println!("NOTE: compiletest thinks it is using GDB version {}", + version.as_slice()); + + if header::gdb_version_to_int(version.as_slice()) > + header::gdb_version_to_int("7.4") { + // Add the directory containing the pretty printers to + // GDB's script auto loading safe path ... + script_str.push_str( + format!("add-auto-load-safe-path {}\n", + rust_pp_module_abs_path.as_slice()) + .as_slice()); + // ... and also the test directory + script_str.push_str( + format!("add-auto-load-safe-path {}\n", + config.build_base.as_str().unwrap()) + .as_slice()); + } + } + _ => { + println!("NOTE: compiletest does not know which version of \ + GDB it is using"); + } + } + + // Load the target executable + script_str.push_str(format!("file {}\n", + exe_file.as_str().unwrap()) + .as_slice()); + + script_str.push_str(cmds.as_slice()); + script_str.push_str("quit\n"); + debug!("script_str = {}", script_str); dump_output_file(config, testfile, script_str.as_slice(), "debugger.script"); + if use_gdb_pretty_printer { + // Only emit the gdb auto-loading script if pretty printers + // should actually be loaded + dump_gdb_autoload_script(config, testfile); + } + // run debugger script with gdb #[cfg(windows)] fn debugger() -> String { @@ -483,16 +534,19 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) { vec!("-quiet".to_string(), "-batch".to_string(), "-nx".to_string(), - format!("-command={}", debugger_script.as_str().unwrap()), - exe_file.as_str().unwrap().to_string()); - proc_args = ProcArgs { + format!("-command={}", debugger_script.as_str().unwrap())); + + let proc_args = ProcArgs { prog: debugger(), args: debugger_opts, }; + + let environment = vec![("PYTHONPATH".to_string(), rust_pp_module_abs_path)]; + debugger_run_result = compose_and_run(config, testfile, proc_args, - Vec::new(), + environment, config.run_lib_path.as_slice(), None, None); @@ -504,6 +558,32 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) { } check_debugger_output(&debugger_run_result, check_lines.as_slice()); + + fn dump_gdb_autoload_script(config: &Config, testfile: &Path) { + let mut script_path = output_base_name(config, testfile); + let mut script_file_name = script_path.filename().unwrap().to_vec(); + script_file_name.push_all("-gdb.py".as_bytes()); + script_path.set_filename(script_file_name.as_slice()); + + let script_content = "import gdb_rust_pretty_printing\n\ + gdb_rust_pretty_printing.register_printers(gdb.current_objfile())\n" + .as_bytes(); + + File::create(&script_path).write(script_content).unwrap(); + } +} + +fn find_rust_src_root(config: &Config) -> Option<Path> { + let mut path = config.src_base.clone(); + let path_postfix = Path::new("src/etc/lldb_batchmode.py"); + + while path.pop() { + if path.join(path_postfix.clone()).is_file() { + return Some(path); + } + } + + return None; } fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path) { @@ -533,7 +613,8 @@ fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path) let DebuggerCommands { commands, check_lines, - breakpoint_lines + breakpoint_lines, + .. } = parse_debugger_commands(testfile, "lldb"); // Write debugger script: @@ -619,6 +700,7 @@ struct DebuggerCommands { commands: Vec<String>, check_lines: Vec<String>, breakpoint_lines: Vec<uint>, + use_gdb_pretty_printer: bool } fn parse_debugger_commands(file_path: &Path, debugger_prefix: &str) @@ -631,6 +713,7 @@ fn parse_debugger_commands(file_path: &Path, debugger_prefix: &str) let mut breakpoint_lines = vec!(); let mut commands = vec!(); let mut check_lines = vec!(); + let mut use_gdb_pretty_printer = false; let mut counter = 1; let mut reader = BufferedReader::new(File::open(file_path).unwrap()); for line in reader.lines() { @@ -640,6 +723,10 @@ fn parse_debugger_commands(file_path: &Path, debugger_prefix: &str) breakpoint_lines.push(counter); } + if line.as_slice().contains("gdb-use-pretty-printer") { + use_gdb_pretty_printer = true; + } + header::parse_name_value_directive( line.as_slice(), command_directive.as_slice()).map(|cmd| { @@ -663,7 +750,8 @@ fn parse_debugger_commands(file_path: &Path, debugger_prefix: &str) DebuggerCommands { commands: commands, check_lines: check_lines, - breakpoint_lines: breakpoint_lines + breakpoint_lines: breakpoint_lines, + use_gdb_pretty_printer: use_gdb_pretty_printer, } } |
