Annotation For tests/utils.rs
Logged in as anonymous

Origin for each line in tests/utils.rs from check-in 98c5a42df0:

dd307557e6 2026-07-31    1: use smtp2tg::utils::{
dd307557e6 2026-07-31    2: 	validate,
dd307557e6 2026-07-31    3: 	RE_CLOSING,
dd307557e6 2026-07-31    4: 	RE_DOMAIN,
dd307557e6 2026-07-31    5: };
6e7d1e877b 2026-07-31    6: 
6e7d1e877b 2026-07-31    7: use std::{
6e7d1e877b 2026-07-31    8: 	borrow::Cow,
6e7d1e877b 2026-07-31    9: 	mem::discriminant,
6e7d1e877b 2026-07-31   10: };
6e7d1e877b 2026-07-31   11: 
98c5a42df0 2026-08-01   12: use stacked_errors::{
98c5a42df0 2026-08-01   13: 	Result,
98c5a42df0 2026-08-01   14: 	ensure_eq,
98c5a42df0 2026-08-01   15: };
6e7d1e877b 2026-07-31   16: 
6e7d1e877b 2026-07-31   17: #[test]
6e7d1e877b 2026-07-31   18: fn test_validate_escaping_behavior () -> Result<()> {
6e7d1e877b 2026-07-31   19: 	let cases: &[(&str, Cow<str>)] = &[
6e7d1e877b 2026-07-31   20: 		// `validate` escapes HTML special characters.
6e7d1e877b 2026-07-31   21: 		("<p>Some <b>valid</b> HTML</p>", Cow::Owned("&lt;p&gt;Some &lt;b&gt;valid&lt;/b&gt; HTML&lt;/p&gt;".into())),
6e7d1e877b 2026-07-31   22: 		// Empty input is returned unchanged.
6e7d1e877b 2026-07-31   23: 		("", Cow::Borrowed("")),
6e7d1e877b 2026-07-31   24: 		// Whitespace-only input needs no escaping.
6e7d1e877b 2026-07-31   25: 		("   \t\n", Cow::Borrowed("   \t\n")),
6e7d1e877b 2026-07-31   26: 		// `validate` returns `Cow<'a, str>` borrowed from its input lifetime `'a`.
6e7d1e877b 2026-07-31   27: 		// These two cases exercise both branches of that `Cow` to make sure the
6e7d1e877b 2026-07-31   28: 		// explicit lifetime introduced on `validate` still lets callers observe a
6e7d1e877b 2026-07-31   29: 		// zero-copy borrow when no escaping is required.
6e7d1e877b 2026-07-31   30: 		("plain text without special html characters", Cow::Borrowed("plain text without special html characters")),
6e7d1e877b 2026-07-31   31: 		("5 > 3 & 2 < 4", Cow::Owned("5 &gt; 3 &amp; 2 &lt; 4".into())),
6e7d1e877b 2026-07-31   32: 	];
6e7d1e877b 2026-07-31   33: 	for (input, expected) in cases {
6e7d1e877b 2026-07-31   34: 		let result = validate(input)?;
98c5a42df0 2026-08-01   35: 		ensure_eq!(&result, expected, format!("unexpected output for input {input:?}"));
98c5a42df0 2026-08-01   36: 		ensure_eq!(discriminant(&result), discriminant(expected), format!("wrong Cow variant for input {input:?}"));
6e7d1e877b 2026-07-31   37: 	}
6e7d1e877b 2026-07-31   38: 	Ok(())
6e7d1e877b 2026-07-31   39: }
6e7d1e877b 2026-07-31   40: 
6e7d1e877b 2026-07-31   41: #[test]
98c5a42df0 2026-08-01   42: fn test_validate_closing_tag_behavior () -> Result<()> {
6e7d1e877b 2026-07-31   43: 	let cases = [
6e7d1e877b 2026-07-31   44: 		("</  pre  >", true),
6e7d1e877b 2026-07-31   45: 		("</\tcode\t>", true),
6e7d1e877b 2026-07-31   46: 		("</b>", false),
6e7d1e877b 2026-07-31   47: 		("</Code>", true),
6e7d1e877b 2026-07-31   48: 		("</code>", true),
6e7d1e877b 2026-07-31   49: 		("</code>\t", true),
6e7d1e877b 2026-07-31   50: 		("</code>\t>", true),
6e7d1e877b 2026-07-31   51: 		("</div>", false), // Not a pre/code tag
6e7d1e877b 2026-07-31   52: 		("</PRE>", true),
6e7d1e877b 2026-07-31   53: 		("</pre>", true),
6e7d1e877b 2026-07-31   54: 		("</pre>\n", true),
6e7d1e877b 2026-07-31   55: 		("<p>Some <b>valid</b> HTML</p></code><a href='http://somewere.com'>Link injection!</a>", true),
6e7d1e877b 2026-07-31   56: 		("<pre>", false),
6e7d1e877b 2026-07-31   57: 	];
6e7d1e877b 2026-07-31   58: 	for (input, expected) in cases {
98c5a42df0 2026-08-01   59: 		ensure_eq!(RE_CLOSING.is_match(input), expected, format!("unexpected match result for {input:?}"));
6e7d1e877b 2026-07-31   60: 	}
98c5a42df0 2026-08-01   61: 	Ok(())
6e7d1e877b 2026-07-31   62: }
6e7d1e877b 2026-07-31   63: 
6e7d1e877b 2026-07-31   64: #[test]
98c5a42df0 2026-08-01   65: fn test_regex_domain_behavior() -> Result<()> {
6e7d1e877b 2026-07-31   66: 	let cases = [
6e7d1e877b 2026-07-31   67: 		("", false),
6e7d1e877b 2026-07-31   68: 		("-example.com", false),
6e7d1e877b 2026-07-31   69: 		(".example.com", false),
6e7d1e877b 2026-07-31   70: 		("123.456", true),
6e7d1e877b 2026-07-31   71: 		("EXAMPLE.COM", false),
6e7d1e877b 2026-07-31   72: 		("a", true),
6e7d1e877b 2026-07-31   73: 		("a.b", true),
6e7d1e877b 2026-07-31   74: 		("example-.com", false),
6e7d1e877b 2026-07-31   75: 		("example..com", false),
6e7d1e877b 2026-07-31   76: 		("example.com", true),
6e7d1e877b 2026-07-31   77: 		("example.com.", false),
6e7d1e877b 2026-07-31   78: 		("invalid@domain.com", false),
6e7d1e877b 2026-07-31   79: 		("my-host.example.com", true),
6e7d1e877b 2026-07-31   80: 		("sub.example.co.uk", true),
6e7d1e877b 2026-07-31   81: 	];
6e7d1e877b 2026-07-31   82: 	for (input, expected) in cases {
98c5a42df0 2026-08-01   83: 		ensure_eq!(RE_DOMAIN.is_match(input), expected, format!("unexpected match result for {input:?}"));
6e7d1e877b 2026-07-31   84: 	}
98c5a42df0 2026-08-01   85: 	Ok(())
dd307557e6 2026-07-31   86: }