Skip to content

Commit

Permalink
debuginfo: Allow debuginfo tests to be ignored based on GDB version.
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelwoerister committed Aug 21, 2014
1 parent e34d36b commit 2eabca9
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 42 deletions.
2 changes: 1 addition & 1 deletion mk/tests.mk
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,7 @@ CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3) := \
--stage-id stage$(1)-$(2) \
--target $(2) \
--host $(3) \
--gdb-version=$(CFG_GDB_VERSION) \
--gdb-version="$(CFG_GDB_VERSION)" \
--android-cross-path=$(CFG_ANDROID_CROSS_PATH) \
--adb-path=$(CFG_ADB) \
--adb-test-dir=$(CFG_ADB_TEST_DIR) \
Expand Down
69 changes: 54 additions & 15 deletions src/compiletest/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> ,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
22 changes: 2 additions & 20 deletions src/compiletest/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ use util::logv;
#[cfg(stage0, target_os = "win32")] // NOTE: Remove after snapshot
use util;

use std::from_str::FromStr;
use std::io::File;
use std::io::fs;
use std::io::net::tcp;
Expand Down Expand Up @@ -318,7 +317,6 @@ actual:\n\
}

fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {

let mut config = Config {
target_rustcflags: cleanup_debug_info_options(&config.target_rustcflags),
host_rustcflags: cleanup_debug_info_options(&config.host_rustcflags),
Expand Down Expand Up @@ -476,7 +474,8 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {

match config.gdb_version {
Some(ref version) => {
if gdb_version_to_int(version.as_slice()) > gdb_version_to_int("7.3") {
if header::gdb_version_to_int(version.as_slice()) >
header::gdb_version_to_int("7.3") {
// Add the directory containing the pretty printers to
// GDB's script auto loading safe path ...
script_str.push_str(
Expand Down Expand Up @@ -567,23 +566,6 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {

File::create(&script_path).write(script_content).unwrap();
}

fn gdb_version_to_int(version_string: &str) -> int {
let error_string = format!(
"Encountered GDB version string with unexpected format: {}",
version_string);

let components: Vec<&str> = version_string.trim().split('.').collect();

if components.len() != 2 {
fatal(error_string.as_slice());
}

let major: int = FromStr::from_str(components[0]).expect(error_string.as_slice());
let minor: int = FromStr::from_str(components[1]).expect(error_string.as_slice());

return major * 1000 + minor;
}
}

fn find_rust_src_root(config: &Config) -> Option<Path> {
Expand Down
16 changes: 11 additions & 5 deletions src/etc/gdb_rust_pretty_printing.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,7 @@ def rust_pretty_printer_lookup_function(val):
discriminant_name, discriminant_val = extract_discriminant_value(val)
return rust_pretty_printer_lookup_function(val[enum_members[discriminant_val]])



# No pretty printer has been found
return None

#=------------------------------------------------------------------------------
Expand All @@ -99,10 +98,17 @@ def to_string(self):
def children(self):
cs = []
for field in self.val.type.fields():
field_name = field.name;
field_name = field.name
# Normally the field name is used as a key to access the field value,
# because that's also supported in older versions of GDB...
field_key = field_name
if field_name == None:
field_name = ""
name_value_tuple = ( field_name, self.val[field] )
# ... but for fields without a name (as in tuples), we have to fall back
# to the newer method of using the field object directly as key. In
# older versions of GDB, this will just fail.
field_key = field
name_value_tuple = ( field_name, self.val[field_key] )
cs.append( name_value_tuple )

if self.hide_first_field:
Expand Down Expand Up @@ -222,4 +228,4 @@ def get_field_at_index(val, index):
for field in val.type.fields():
if i == index:
return field
return None
return None
75 changes: 75 additions & 0 deletions src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// 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.

// This test uses only GDB Python API features which should be available in
// older versions of GDB too. A more extensive test can be found in
// gdb-pretty-struct-and-enums.rs

// ignore-tidy-linelength
// ignore-lldb
// ignore-android: FIXME(#10381)
// compile-flags:-g
// gdb-use-pretty-printer

// The following line actually doesn't have to do anything with pretty printing,
// it just tells GDB to print values on one line:
// gdb-command: set print pretty off

// gdb-command: rbreak zzz
// gdb-command: run
// gdb-command: finish

// gdb-command: print regular_struct
// gdb-check:$1 = RegularStruct = {the_first_field = 101, the_second_field = 102.5, the_third_field = false}

// gdb-command: print empty_struct
// gdb-check:$2 = EmptyStruct

// gdb-command: print c_style_enum1
// gdb-check:$3 = CStyleEnumVar1

// gdb-command: print c_style_enum2
// gdb-check:$4 = CStyleEnumVar2

// gdb-command: print c_style_enum3
// gdb-check:$5 = CStyleEnumVar3

struct RegularStruct {
the_first_field: int,
the_second_field: f64,
the_third_field: bool,
}

struct EmptyStruct;

enum CStyleEnum {
CStyleEnumVar1,
CStyleEnumVar2,
CStyleEnumVar3,
}

fn main() {

let regular_struct = RegularStruct {
the_first_field: 101,
the_second_field: 102.5,
the_third_field: false
};

let empty_struct = EmptyStruct;

let c_style_enum1 = CStyleEnumVar1;
let c_style_enum2 = CStyleEnumVar2;
let c_style_enum3 = CStyleEnumVar3;

zzz();
}

fn zzz() { () }
7 changes: 6 additions & 1 deletion src/test/debuginfo/gdb-pretty-struct-and-enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
// compile-flags:-g
// gdb-use-pretty-printer

// This test uses some GDB Python API features (e.g. accessing anonymous fields)
// which are only available in newer GDB version. The following directive will
// case the test runner to ignore this test if an older GDB version is used:
// min-gdb-version 7.7

// The following line actually doesn't have to do anything with pretty printing,
// it just tells GDB to print values on one line:
// gdb-command: set print pretty off
Expand Down Expand Up @@ -164,4 +169,4 @@ fn main() {
zzz();
}

fn zzz() { () }
fn zzz() { () }

0 comments on commit 2eabca9

Please sign in to comment.