diff --git a/configure b/configure index 15f005e0da6..d9f2db8e110 100755 --- a/configure +++ b/configure @@ -394,6 +394,7 @@ probe CFG_PDFLATEX pdflatex probe CFG_XETEX xetex probe CFG_LUATEX luatex probe CFG_NODE nodejs node +probe CFG_GDB gdb if [ "$CFG_OSTYPE" = "unknown-linux-gnu" ] then probe CFG_PAXCTL paxctl /sbin/paxctl @@ -619,6 +620,7 @@ do make_dir $h/test/bench make_dir $h/test/perf make_dir $h/test/pretty + make_dir $h/test/debug-info make_dir $h/test/doc-tutorial make_dir $h/test/doc-tutorial-ffi make_dir $h/test/doc-tutorial-macros diff --git a/mk/tests.mk b/mk/tests.mk index 2c1b19486af..abe9ba60ecd 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -103,7 +103,8 @@ cleantestlibs: -name '*.dSYM' -o \ -name '*.libaux' -o \ -name '*.out' -o \ - -name '*.err' \ + -name '*.err' -o \ + -name '*.debugger.script' \ | xargs rm -rf @@ -170,6 +171,7 @@ check-stage$(1)-T-$(2)-H-$(3)-exec: \ check-stage$(1)-T-$(2)-H-$(3)-rpass-full-exec \ check-stage$(1)-T-$(2)-H-$(3)-crates-exec \ check-stage$(1)-T-$(2)-H-$(3)-bench-exec \ + check-stage$(1)-T-$(2)-H-$(3)-debuginfo-exec \ check-stage$(1)-T-$(2)-H-$(3)-doc-exec \ check-stage$(1)-T-$(2)-H-$(3)-pretty-exec @@ -284,6 +286,7 @@ CFAIL_RC := $(wildcard $(S)src/test/compile-fail/*.rc) CFAIL_RS := $(wildcard $(S)src/test/compile-fail/*.rs) BENCH_RS := $(wildcard $(S)src/test/bench/*.rs) PRETTY_RS := $(wildcard $(S)src/test/pretty/*.rs) +DEBUGINFO_RS := $(wildcard $(S)src/test/debug-info/*.rs) # perf tests are the same as bench tests only they run under # a performance monitor. @@ -296,6 +299,7 @@ CFAIL_TESTS := $(CFAIL_RC) $(CFAIL_RS) BENCH_TESTS := $(BENCH_RS) PERF_TESTS := $(PERF_RS) PRETTY_TESTS := $(PRETTY_RS) +DEBUGINFO_TESTS := $(DEBUGINFO_RS) CTEST_SRC_BASE_rpass = run-pass CTEST_BUILD_BASE_rpass = run-pass @@ -327,6 +331,15 @@ CTEST_BUILD_BASE_perf = perf CTEST_MODE_perf = run-pass CTEST_RUNTOOL_perf = $(CTEST_PERF_RUNTOOL) +CTEST_SRC_BASE_debuginfo = debug-info +CTEST_BUILD_BASE_debuginfo = debug-info +CTEST_MODE_debuginfo = debug-info +CTEST_RUNTOOL_debuginfo = $(CTEST_RUNTOOL) + +ifeq ($(CFG_GDB),) +CTEST_DISABLE_debuginfo = "no gdb found" +endif + define DEF_CTEST_VARS # All the per-stage build rules you might want to call from the @@ -349,7 +362,7 @@ CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3) := \ --rustc-path $$(HBIN$(1)_H_$(3))/rustc$$(X) \ --aux-base $$(S)src/test/auxiliary/ \ --stage-id stage$(1)-$(2) \ - --rustcflags "$$(CFG_RUSTC_FLAGS) --target=$(2)" \ + --rustcflags "$$(CFG_RUSTC_FLAGS) --target=$(2)" \ $$(CTEST_TESTARGS) CTEST_DEPS_rpass_$(1)-T-$(2)-H-$(3) = $$(RPASS_TESTS) @@ -358,6 +371,7 @@ CTEST_DEPS_rfail_$(1)-T-$(2)-H-$(3) = $$(RFAIL_TESTS) CTEST_DEPS_cfail_$(1)-T-$(2)-H-$(3) = $$(CFAIL_TESTS) CTEST_DEPS_bench_$(1)-T-$(2)-H-$(3) = $$(BENCH_TESTS) CTEST_DEPS_perf_$(1)-T-$(2)-H-$(3) = $$(PERF_TESTS) +CTEST_DEPS_debuginfo_$(1)-T-$(2)-H-$(3) = $$(DEBUGINFO_TESTS) endef @@ -377,6 +391,8 @@ CTEST_ARGS$(1)-T-$(2)-H-$(3)-$(4) := \ check-stage$(1)-T-$(2)-H-$(3)-$(4)-exec: $$(call TEST_OK_FILE,$(1),$(2),$(3),$(4)) +ifeq ($$(CTEST_DISABLE_$(4)),) + $$(call TEST_OK_FILE,$(1),$(2),$(3),$(4)): \ $$(TEST_SREQ$(1)_T_$(2)_H_$(3)) \ $$(CTEST_DEPS_$(4)_$(1)-T-$(2)-H-$(3)) @@ -386,9 +402,20 @@ $$(call TEST_OK_FILE,$(1),$(2),$(3),$(4)): \ --logfile $$(call TEST_LOG_FILE,$(1),$(2),$(3),$(4)) \ && touch $$@ +else + +$$(call TEST_OK_FILE,$(1),$(2),$(3),$(4)): \ + $$(TEST_SREQ$(1)_T_$(2)_H_$(3)) \ + $$(CTEST_DEPS_$(4)_$(1)-T-$(2)-H-$(3)) + @$$(call E, run $(4): $$<) + @$$(call E, warning: tests disabled: $$(CTEST_DISABLE_$(4))) + touch $$@ + +endif + endef -CTEST_NAMES = rpass rpass-full rfail cfail bench perf +CTEST_NAMES = rpass rpass-full rfail cfail bench perf debuginfo $(foreach host,$(CFG_TARGET_TRIPLES), \ $(eval $(foreach target,$(CFG_TARGET_TRIPLES), \ @@ -496,6 +523,7 @@ TEST_GROUPS = \ cfail \ bench \ perf \ + debuginfo \ doc \ $(foreach docname,$(DOC_TEST_NAMES),$(docname)) \ pretty \ diff --git a/src/compiletest/common.rs b/src/compiletest/common.rs index 9d4becd63d3..679f9ab93bf 100644 --- a/src/compiletest/common.rs +++ b/src/compiletest/common.rs @@ -1,5 +1,5 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at +// Copyright 2012-2013 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 mode { ~"run-fail" => mode_run_fail, ~"run-pass" => mode_run_pass, ~"pretty" => mode_pretty, + ~"debug-info" => mode_debug_info, _ => die!(~"invalid mode") } } @@ -140,7 +142,8 @@ pub fn mode_str(mode: mode) -> ~str { mode_compile_fail => ~"compile-fail", mode_run_fail => ~"run-fail", mode_run_pass => ~"run-pass", - mode_pretty => ~"pretty" + mode_pretty => ~"pretty", + mode_debug_info => ~"debug-info", } } diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index 0b9d67426ae..5c33c66209a 100644 --- a/src/compiletest/header.rs +++ b/src/compiletest/header.rs @@ -1,5 +1,5 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at +// Copyright 2012-2013 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 TestProps { let mut exec_env = ~[]; let mut compile_flags = None; let mut pp_exact = None; + let mut debugger_cmds = ~[]; + let mut check_lines = ~[]; for iter_header(testfile) |ln| { match parse_error_pattern(ln) { Some(ep) => error_patterns.push(ep), @@ -59,13 +65,25 @@ pub fn load_props(testfile: &Path) -> TestProps { do parse_exec_env(ln).iter |ee| { exec_env.push(*ee); } + + match parse_debugger_cmd(ln) { + Some(dc) => debugger_cmds.push(dc), + None => () + }; + + match parse_check_line(ln) { + Some(cl) => check_lines.push(cl), + None => () + }; }; return TestProps { error_patterns: error_patterns, compile_flags: compile_flags, pp_exact: pp_exact, aux_builds: aux_builds, - exec_env: exec_env + exec_env: exec_env, + debugger_cmds: debugger_cmds, + check_lines: check_lines }; } @@ -112,6 +130,14 @@ fn parse_compile_flags(line: ~str) -> Option<~str> { parse_name_value_directive(line, ~"compile-flags") } +fn parse_debugger_cmd(line: ~str) -> Option<~str> { + parse_name_value_directive(line, ~"debugger") +} + +fn parse_check_line(line: ~str) -> Option<~str> { + parse_name_value_directive(line, ~"check") +} + fn parse_exec_env(line: ~str) -> Option<(~str, ~str)> { do parse_name_value_directive(line, ~"exec-env").map |nv| { // nv is either FOO or FOO=BAR diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index a71b8a360a2..0f8c8761c42 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -1,5 +1,5 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at +// Copyright 2012-2013 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 run_cfail_test(config, props, &testfile), mode_run_fail => run_rfail_test(config, props, &testfile), mode_run_pass => run_rpass_test(config, props, &testfile), - mode_pretty => run_pretty_test(config, props, &testfile) + mode_pretty => run_pretty_test(config, props, &testfile), + mode_debug_info => run_debuginfo_test(config, props, &testfile) } } @@ -224,6 +226,55 @@ actual:\n\ } } +fn run_debuginfo_test(config: config, props: TestProps, testfile: &Path) { + // compile test file (it shoud have 'compile-flags:-g' in the header) + let mut ProcRes = compile_test(config, props, testfile); + if ProcRes.status != 0 { + fatal_ProcRes(~"compilation failed!", ProcRes); + } + + // write debugger script + let script_str = str::append(str::connect(props.debugger_cmds, "\n"), + ~"\nquit\n"); + debug!("script_str = %s", script_str); + dump_output_file(config, testfile, script_str, ~"debugger.script"); + + // run debugger script with gdb + #[cfg(windows)] + fn debugger() -> ~str { ~"gdb.exe" } + #[cfg(unix)] + fn debugger() -> ~str { ~"gdb" } + let debugger_script = make_out_name(config, testfile, ~"debugger.script"); + let debugger_opts = ~[~"-quiet", ~"-batch", ~"-nx", + ~"-command=" + debugger_script.to_str(), + make_exe_name(config, testfile).to_str()]; + let ProcArgs = ProcArgs {prog: debugger(), args: debugger_opts}; + ProcRes = compose_and_run(config, testfile, ProcArgs, ~[], ~"", None); + if ProcRes.status != 0 { + fatal(~"gdb failed to execute"); + } + + let num_check_lines = vec::len(props.check_lines); + if num_check_lines > 0 { + // check if each line in props.check_lines appears in the + // output (in order) + let mut i = 0u; + for str::lines(ProcRes.stdout).each |line| { + if props.check_lines[i].trim() == line.trim() { + i += 1u; + } + if i == num_check_lines { + // all lines checked + break; + } + } + if i != num_check_lines { + fatal(fmt!("line not found in debugger output: %s", + props.check_lines[i])); + } + } +} + fn check_error_patterns(props: TestProps, testfile: &Path, ProcRes: ProcRes) { diff --git a/src/test/debug-info/simple.rs b/src/test/debug-info/simple.rs new file mode 100644 index 00000000000..51bb177601a --- /dev/null +++ b/src/test/debug-info/simple.rs @@ -0,0 +1,21 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// xfail-test +// compile-flags:-g +// debugger:break 20 +// debugger:run +// debugger:print x +// check:$1 = 42 + +fn main() { + let x = 42; + debug!("The answer is %d", x); +} diff --git a/src/test/debug-info/struct.rs b/src/test/debug-info/struct.rs new file mode 100644 index 00000000000..b3132914477 --- /dev/null +++ b/src/test/debug-info/struct.rs @@ -0,0 +1,33 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// xfail-test +// compile-flags:-g +// debugger:break 32 +// debugger:run +// debugger:print pair +// check:$1 = { +// check:x = 1, +// check:y = 2, +// check:} +// debugger:print pair.x +// check:$2 = 1 +// debugger:print pair.y +// check:$3 = 2 + +struct Pair { + x: int, + y: int +} + +fn main() { + let pair = Pair { x: 1, y: 2 }; + debug!("x = %d, y = %d", pair.x, pair.y); +}