From d94112fae0a6a525ffbcff67ba19f29d0050c513 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 29 Nov 2025 10:05:24 +0000 Subject: [PATCH 1/4] Initial plan From d6a804869d03c13934f0af465170d788d41781d6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 29 Nov 2025 10:18:56 +0000 Subject: [PATCH 2/4] Add revision support to debuginfo test commands Co-authored-by: Enselic <115040+Enselic@users.noreply.github.com> --- src/tools/compiletest/src/runtest/debugger.rs | 74 ++++++++++++++++++- .../compiletest/src/runtest/debuginfo.rs | 6 +- 2 files changed, 73 insertions(+), 7 deletions(-) diff --git a/src/tools/compiletest/src/runtest/debugger.rs b/src/tools/compiletest/src/runtest/debugger.rs index 00935ab57d1c3..277bd8e6d3b7c 100644 --- a/src/tools/compiletest/src/runtest/debugger.rs +++ b/src/tools/compiletest/src/runtest/debugger.rs @@ -19,7 +19,11 @@ pub(super) struct DebuggerCommands { } impl DebuggerCommands { - pub fn parse_from(file: &Utf8Path, debugger_prefix: &str) -> Result { + pub fn parse_from( + file: &Utf8Path, + debugger_prefix: &str, + test_revision: Option<&str>, + ) -> Result { let command_directive = format!("{debugger_prefix}-command"); let check_directive = format!("{debugger_prefix}-check"); @@ -38,14 +42,49 @@ impl DebuggerCommands { continue; } - let Some(line) = line.trim_start().strip_prefix("//@").map(str::trim_start) else { + let Some(after_prefix) = line.trim_start().strip_prefix("//@").map(str::trim_start) + else { continue; }; - if let Some(command) = parse_name_value(&line, &command_directive) { + // Handle revision-specific directives like `//@ [revision] directive` + // by stripping the revision prefix if present + let (line_revision, directive_line) = + if let Some(after_open_bracket) = after_prefix.strip_prefix('[') { + if let Some((revision, after_close_bracket)) = + after_open_bracket.split_once(']') + { + (Some(revision), after_close_bracket.trim_start()) + } else { + // Malformed revision prefix, skip this line + continue; + } + } else { + (None, after_prefix) + }; + + // Only process directives that apply to the current revision: + // - Directives without a revision prefix apply to all revisions + // - Directives with a revision prefix only apply when it matches the test revision + let dominated_by_test_revision = match (test_revision, line_revision) { + // Only error messages that contain our revision between the square brackets + // apply to us. + (Some(test_rev), Some(line_rev)) => test_rev == line_rev, + // No test revision means we're not running a revisioned test, + // so directives with revision prefixes shouldn't be processed + (None, Some(_)) => false, + // If a directive has no revision prefix, it applies to all revisions + (_, None) => true, + }; + + if !dominated_by_test_revision { + continue; + } + + if let Some(command) = parse_name_value(directive_line, &command_directive) { commands.push(command); } - if let Some(pattern) = parse_name_value(&line, &check_directive) { + if let Some(pattern) = parse_name_value(directive_line, &check_directive) { check_lines.push((line_no, pattern)); } } @@ -150,3 +189,30 @@ fn check_single_line(line: &str, check_line: &str) -> bool { can_end_anywhere || rest.is_empty() } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_check_single_line_exact_match() { + assert!(check_single_line("$1 = 42", "$1 = 42")); + assert!(!check_single_line("$1 = 42", "$1 = 43")); + } + + #[test] + fn test_check_single_line_with_wildcard() { + assert!(check_single_line("$1 = 42 (some extra stuff)", "$1 = 42[...]")); + assert!(check_single_line("prefix $1 = 42 suffix", "[...]$1 = 42[...]")); + assert!(!check_single_line("$1 = 43", "$1 = 42[...]")); + } + + #[test] + fn test_parse_name_value() { + assert_eq!(parse_name_value("gdb-command:run", "gdb-command"), Some("run".to_string())); + assert_eq!(parse_name_value("gdb-command:", "gdb-command"), Some("".to_string())); + assert_eq!(parse_name_value("gdb-check:$1 = 42", "gdb-check"), Some("$1 = 42".to_string())); + assert_eq!(parse_name_value("lldb-command:run", "gdb-command"), None); + assert_eq!(parse_name_value("gdb-command run", "gdb-command"), None); + } +} diff --git a/src/tools/compiletest/src/runtest/debuginfo.rs b/src/tools/compiletest/src/runtest/debuginfo.rs index 15e37cda7d965..c73cce1332e6d 100644 --- a/src/tools/compiletest/src/runtest/debuginfo.rs +++ b/src/tools/compiletest/src/runtest/debuginfo.rs @@ -46,7 +46,7 @@ impl TestCx<'_> { } // Parse debugger commands etc from test files - let dbg_cmds = DebuggerCommands::parse_from(&self.testpaths.file, "cdb") + let dbg_cmds = DebuggerCommands::parse_from(&self.testpaths.file, "cdb", self.revision) .unwrap_or_else(|e| self.fatal(&e)); // https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-commands @@ -105,7 +105,7 @@ impl TestCx<'_> { } fn run_debuginfo_gdb_test(&self) { - let dbg_cmds = DebuggerCommands::parse_from(&self.testpaths.file, "gdb") + let dbg_cmds = DebuggerCommands::parse_from(&self.testpaths.file, "gdb", self.revision) .unwrap_or_else(|e| self.fatal(&e)); let mut cmds = dbg_cmds.commands.join("\n"); @@ -360,7 +360,7 @@ impl TestCx<'_> { } // Parse debugger commands etc from test files - let dbg_cmds = DebuggerCommands::parse_from(&self.testpaths.file, "lldb") + let dbg_cmds = DebuggerCommands::parse_from(&self.testpaths.file, "lldb", self.revision) .unwrap_or_else(|e| self.fatal(&e)); // Write debugger script: From 805d8d9580ef867c5e059c90038f04752202a3a9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 29 Nov 2025 10:21:02 +0000 Subject: [PATCH 3/4] Fix code review comments: update comment and fix typo Co-authored-by: Enselic <115040+Enselic@users.noreply.github.com> --- src/tools/compiletest/src/runtest/debugger.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/tools/compiletest/src/runtest/debugger.rs b/src/tools/compiletest/src/runtest/debugger.rs index 277bd8e6d3b7c..23e8c1fbf2ae6 100644 --- a/src/tools/compiletest/src/runtest/debugger.rs +++ b/src/tools/compiletest/src/runtest/debugger.rs @@ -8,7 +8,7 @@ use crate::runtest::ProcRes; /// Representation of information to invoke a debugger and check its output pub(super) struct DebuggerCommands { - /// Commands for the debuuger + /// Commands for the debugger pub commands: Vec, /// Lines to insert breakpoints at pub breakpoint_lines: Vec, @@ -66,9 +66,8 @@ impl DebuggerCommands { // Only process directives that apply to the current revision: // - Directives without a revision prefix apply to all revisions // - Directives with a revision prefix only apply when it matches the test revision - let dominated_by_test_revision = match (test_revision, line_revision) { - // Only error messages that contain our revision between the square brackets - // apply to us. + let applies_to_revision = match (test_revision, line_revision) { + // Directives with a revision prefix only apply to that specific revision (Some(test_rev), Some(line_rev)) => test_rev == line_rev, // No test revision means we're not running a revisioned test, // so directives with revision prefixes shouldn't be processed @@ -77,7 +76,7 @@ impl DebuggerCommands { (_, None) => true, }; - if !dominated_by_test_revision { + if !applies_to_revision { continue; } From 12acdc4604ade3e82d8e767ae138c4de16cc035d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 29 Nov 2025 14:49:45 +0000 Subject: [PATCH 4/4] Include revision in debuginfo test failure messages Co-authored-by: Enselic <115040+Enselic@users.noreply.github.com> --- src/tools/compiletest/src/runtest/debugger.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/tools/compiletest/src/runtest/debugger.rs b/src/tools/compiletest/src/runtest/debugger.rs index 23e8c1fbf2ae6..51645eb3a3592 100644 --- a/src/tools/compiletest/src/runtest/debugger.rs +++ b/src/tools/compiletest/src/runtest/debugger.rs @@ -16,6 +16,8 @@ pub(super) struct DebuggerCommands { check_lines: Vec<(usize, String)>, /// Source file name file: Utf8PathBuf, + /// The revision being tested, if any + revision: Option, } impl DebuggerCommands { @@ -88,7 +90,13 @@ impl DebuggerCommands { } } - Ok(Self { commands, breakpoint_lines, check_lines, file: file.to_path_buf() }) + Ok(Self { + commands, + breakpoint_lines, + check_lines, + file: file.to_path_buf(), + revision: test_revision.map(str::to_owned), + }) } /// Given debugger output and lines to check, ensure that every line is @@ -120,9 +128,11 @@ impl DebuggerCommands { Ok(()) } else { let fname = self.file.file_name().unwrap(); + let revision_suffix = + self.revision.as_ref().map_or(String::new(), |r| format!("#{}", r)); let mut msg = format!( - "check directive(s) from `{}` not found in debugger output. errors:", - self.file + "check directive(s) from `{}{}` not found in debugger output. errors:", + self.file, revision_suffix ); for (src_lineno, err_line) in missing {