tor_netdoc/
test_support.rs1#![allow(clippy::bool_assert_comparison)]
4#![allow(clippy::clone_on_copy)]
5#![allow(clippy::dbg_macro)]
6#![allow(clippy::mixed_attributes_style)]
7#![allow(clippy::print_stderr)]
8#![allow(clippy::print_stdout)]
9#![allow(clippy::single_char_pattern)]
10#![allow(clippy::unwrap_used)]
11#![allow(clippy::unchecked_time_subtraction)]
12#![allow(clippy::useless_vec)]
13#![allow(clippy::needless_pass_by_value)]
14#![allow(clippy::string_slice)] use crate::parse2::{NetdocParseableFields, ParseInput, parse_netdoc};
18use derive_deftly::Deftly;
19use itertools::chain;
20use std::fmt::Display;
21
22#[cfg(any(test, feature = "testing"))]
26#[macro_export]
27macro_rules! assert_eq_or_diff {
28 { $a:expr, $b:expr $(,)? } => {
29 assert_eq_or_diff!($a, $b, "")
30 };
31 { $a:expr, $b:expr , $($message:tt)*} => {
32 $crate::assert_eq_or_diff(
33 &$a,
34 stringify!($a),
35 &$b,
36 stringify!($b),
37 &format_args!($($message)*),
38 )
39 };
40}
41
42#[cfg(any(test, feature = "testing"))]
46pub fn assert_eq_or_diff(a: &str, a_what: &str, b: &str, b_what: &str, message: &dyn Display) {
47 use imara_diff::{Algorithm, BasicLineDiffPrinter, Diff, InternedInput, UnifiedDiffConfig};
48
49 if a == b {
50 return;
51 }
52 let input = InternedInput::new(a, b);
53 let mut diff = Diff::compute(Algorithm::Histogram, &input);
54 diff.postprocess_lines(&input);
55 panic!(
56 "===== document {a_what} =====
58{a}
59===== document {b_what} =====
60{b}
61===== diff ====
62{}
63===== documents differ: {a_what} != {b_what} =====
64{message}
65",
66 diff.unified_diff(
67 &BasicLineDiffPrinter(&input.interner),
68 UnifiedDiffConfig::default(),
69 &input,
70 ),
71 );
72}
73
74pub fn regsub(update: &mut String, re: &str, repl: impl regex::Replacer) {
81 *update = regex::Regex::new(&format!("(?m){re}"))
82 .expect(re)
83 .replace_all(update, repl)
84 .to_string();
85}
86
87pub fn parse_testcase_from_netdoc<T: NetdocParseableFields>(input_doc: &str) -> T {
98 #[derive(Deftly)]
99 #[derive_deftly(NetdocParseable)]
100 struct Document<T: NetdocParseableFields> {
101 #[allow(unused)]
103 parse_testcase_from_netdoc_intro: (),
104
105 #[deftly(netdoc(flatten))]
106 fields: T,
107 }
108
109 eprintln!("\n&&&&&&& input test case\n{input_doc}");
110 let doc = chain!(
111 ["parse-testcase-from-netdoc-intro\n"],
112 input_doc
113 .lines()
114 .map(|l| l.split_once('#').map(|(l, _)| l).unwrap_or(l).trim())
115 .filter(|l| !l.is_empty())
116 .flat_map(|l| [l, "\n"]),
117 )
118 .collect::<String>();
119
120 eprintln!(
121 "---- tidied \n{}----",
122 doc.split_inclusive('\n')
123 .enumerate()
125 .map(|(lno, l)| format!("| {:5} {l}", lno + 1))
126 .collect::<String>()
127 );
128
129 let pinput = ParseInput::new(&doc, "<input doc>");
130 let case: Document<T> = parse_netdoc(&pinput).expect("parse failed");
131
132 case.fields
133}