Skip to main content

miden_assembly_syntax/testing/
mod.rs

1#[cfg(test)]
2mod context;
3mod pattern;
4
5#[cfg(test)]
6pub use self::context::SyntaxTestContext;
7pub use self::pattern::Pattern;
8
9/// Create a [Pattern::Regex] from the given input
10#[macro_export]
11macro_rules! regex {
12    ($source:literal) => {
13        $crate::testing::Pattern::regex($source)
14    };
15
16    ($source:expr) => {
17        $crate::testing::Pattern::regex($source)
18    };
19}
20
21/// Construct an [`::alloc::sync::Arc<miden_core::debuginfo::SourceFile>`] from a string literal or
22/// expression, such that emitted diagnostics reference the file and line on which the source file
23/// was constructed.
24#[macro_export]
25macro_rules! source_file {
26    ($context:expr, $source:literal) => {
27        $context.source_manager().load(
28            $crate::debuginfo::SourceLanguage::Masm,
29            concat!("test", line!()).into(),
30            $source.to_string(),
31        )
32    };
33    ($context:expr, $source:expr) => {
34        $context.source_manager().load(
35            $crate::debuginfo::SourceLanguage::Masm,
36            concat!("test", line!()).into(),
37            $source.to_string(),
38        )
39    };
40}
41
42/// Assert that the given diagnostic/error value, when rendered to stdout,
43/// contains the given pattern
44#[macro_export]
45macro_rules! assert_diagnostic {
46    ($diagnostic:expr, $expected:literal) => {{
47        let actual = format!(
48            "{}",
49            $crate::diagnostics::reporting::PrintDiagnostic::new_without_color($diagnostic)
50        );
51        $crate::testing::Pattern::from($expected).assert_match(actual);
52    }};
53
54    ($diagnostic:expr, $expected:expr) => {{
55        let actual = format!(
56            "{}",
57            $crate::diagnostics::reporting::PrintDiagnostic::new_without_color($diagnostic)
58        );
59        $crate::testing::Pattern::from($expected).assert_match(actual);
60    }};
61}
62
63/// Like [assert_diagnostic], but matches each non-empty line of the rendered output to a
64/// corresponding pattern.
65///
66/// Empty lines are ignored, but the remaining line count must match the number of patterns.
67#[macro_export]
68macro_rules! assert_diagnostic_lines {
69    ($diagnostic:expr, $($expected_lines:expr),+) => {{
70        let full_output = format!("{}", $crate::diagnostics::reporting::PrintDiagnostic::new_without_color($diagnostic));
71        let lines: Vec<_> = full_output.lines().filter(|l| !l.trim().is_empty()).collect();
72        let patterns = [$($crate::testing::Pattern::from($expected_lines)),*];
73        if lines.len() != patterns.len() {
74            panic!(
75                "expected {} lines, but got {}:\n{}",
76                patterns.len(),
77                lines.len(),
78                full_output
79            );
80        }
81        let lines_and_patterns = lines.into_iter().zip(patterns.into_iter());
82        for (actual_line, expected_pattern) in lines_and_patterns {
83            expected_pattern.assert_match_with_context(actual_line, &full_output);
84        }
85    }};
86}
87
88#[macro_export]
89macro_rules! parse_module {
90    ($context:expr, $source:expr) => {{
91        let source_file = $context.source_manager().load(
92            $crate::debuginfo::SourceLanguage::Masm,
93            concat!("test", line!()).into(),
94            ::alloc::string::String::from($source),
95        );
96        let mut parser = $crate::ast::Module::parser(None);
97        parser
98            .parse(None, source_file, $context.source_manager())
99            .expect("failed to parse module")
100    }};
101}