debugger_test_parser/
lib.rs1use regex::Regex;
2
3enum OutputParsingStyle {
4 LiteralMatch(String),
5 PatternMatch(Regex),
6}
7
8const PATTERN_PREFIX: &str = "pattern:";
9
10pub fn parse(debugger_output: String, expected_contents: Vec<&str>) -> anyhow::Result<()> {
14 if expected_contents.len() == 0 {
16 log::info!("No expected contents found.");
17 return anyhow::Ok(());
18 }
19
20 let debugger_output_lines = debugger_output
22 .trim()
23 .lines()
24 .map(|line| line.trim())
25 .collect::<Vec<&str>>();
26
27 let expected_contents = expected_contents
29 .iter()
30 .filter_map(|line| {
31 let str = line.trim();
32 match str.is_empty() {
33 false => Some(str),
34 true => None,
35 }
36 })
37 .map(|line| line.trim())
38 .collect::<Vec<&str>>();
39
40 let mut index = 0;
41
42 for expected in expected_contents {
43 let parsing_style = get_output_parsing_style(expected)?;
44 loop {
45 if index >= debugger_output_lines.len() {
46 let error_msg = format_error_message(&parsing_style);
47 anyhow::bail!(
48 "Unable to find expected content in the debugger output. {}",
49 error_msg
50 );
51 }
52
53 let debugger_output_line = debugger_output_lines[index];
54 index += 1;
55
56 match &parsing_style {
58 OutputParsingStyle::LiteralMatch(literal_str) => {
59 let str = literal_str.as_str();
60 if debugger_output_line.contains(&str) {
61 log::info!(
62 "Expected content found: `{}` at line `{}`",
63 str,
64 debugger_output_line
65 );
66 break;
67 }
68 }
69 OutputParsingStyle::PatternMatch(re) => {
70 if re.is_match(&debugger_output_line) {
71 log::info!("Expected pattern found: `{}`", debugger_output_line);
72 break;
73 }
74 }
75 }
76 }
77 }
78
79 anyhow::Ok(())
80}
81
82fn format_error_message(parsing_style: &OutputParsingStyle) -> String {
83 match parsing_style {
84 OutputParsingStyle::LiteralMatch(literal_string) => {
85 format!("Missing line: `{}`", literal_string)
86 }
87 OutputParsingStyle::PatternMatch(pattern) => {
88 format!("Found 0 matches for pattern: `{}`", pattern.to_string())
89 }
90 }
91}
92
93fn get_output_parsing_style(expected_output: &str) -> anyhow::Result<OutputParsingStyle> {
95 let parsing_style = if expected_output.starts_with(PATTERN_PREFIX) {
96 let re_pattern = expected_output
97 .strip_prefix(PATTERN_PREFIX)
98 .expect("string starts with `pattern:`");
99 let re = match Regex::new(re_pattern) {
100 Ok(re) => re,
101 Err(error) => anyhow::bail!("Invalid regex pattern: {}\n{}", re_pattern, error),
102 };
103
104 OutputParsingStyle::PatternMatch(re)
105 } else {
106 OutputParsingStyle::LiteralMatch(String::from(expected_output))
107 };
108
109 Ok(parsing_style)
110}