Annotation For tests/utils.rs
Logged in as anonymous

Lines of tests/utils.rs from check-in 6e7d1e877b that are changed by the sequence of edits moving toward check-in 98c5a42df0:

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