const PROVENANCE: &str = include_str!("../docs/provenance.md");
fn segmentation_version() -> String {
let (major, minor, patch) = unicode_segmentation::UNICODE_VERSION;
format!("{major}.{minor}.{patch}")
}
fn segmentation_row() -> &'static str {
PROVENANCE
.lines()
.find(|line| line.contains("unicode-segmentation"))
.expect("docs/provenance.md has no `unicode-segmentation` row")
}
#[test]
fn provenance_states_the_resolved_segmentation_version() {
let version = segmentation_version();
assert!(
segmentation_row().contains(&version),
"docs/provenance.md's grapheme-segmentation row does not state {version}, which is \
what `unicode-segmentation` resolves to now.\n\nrow: {}\n\nA `cargo update` moved \
the UAX #29 tables. Update the row (and #645's constant, if it exists by then).",
segmentation_row()
);
}
const UTS46: &[(&str, &str)] = &[
(
"xn--80ak6aa92e.com",
"\u{430}\u{440}\u{440}\u{4cf}\u{435}.com",
),
("xn--pple-43d.com", "\u{430}pple.com"),
("xn--e1awd7f.com", "\u{435}\u{440}\u{456}\u{441}.com"),
("xn--nxasmm1c.gr", "\u{3b2}\u{3cc}\u{3bb}\u{3bf}\u{3c2}.gr"),
("xn--mgbh0fb.eg", "\u{645}\u{62b}\u{627}\u{644}.eg"),
("xn--zckzah.jp", "\u{30c6}\u{30b9}\u{30c8}.jp"),
("xn--fiqs8s", "\u{4e2d}\u{56fd}"),
("XN--PPLE-43D.COM", "\u{430}pple.com"),
("ExAmPlE.COM", "example.com"),
("B\u{fc}cher.de", "b\u{fc}cher.de"),
("\u{2460}.com", "1.com"),
("\u{216b}.com", "xii.com"),
("\u{2121}.com", "tel.com"),
("xn--fa-hia.de", "fa\u{df}.de"),
("fa\u{df}.de", "fa\u{df}.de"),
];
#[test]
fn uts46_behaviour_has_not_moved() {
let mut moved = Vec::new();
for (input, expected) in UTS46 {
let (got, errors) = idna::domain_to_unicode(input);
if errors.is_err() {
moved.push(format!("{input:?} now fails validation (was {expected:?})"));
} else if got != *expected {
moved.push(format!("{input:?} -> {got:?}, was {expected:?}"));
}
}
assert!(
moved.is_empty(),
"UTS #46 behaviour moved under `idna`:\n {}\n\n`idna` publishes no version \
constant, so this snapshot is the gate. A change here means `cargo update` moved \
the ICU4X data behind `is_suspicious_hostname`, and the same registry entries now \
decode differently. Re-measure, decide whether the new answers are right, then \
update this table and the `idna` row in docs/provenance.md.",
moved.join("\n ")
);
}
#[test]
fn the_snapshot_can_fail() {
let (got, _) = idna::domain_to_unicode("xn--pple-43d.com");
assert_ne!(got, "not-what-idna-returns.com");
assert_eq!(got, "\u{430}pple.com");
}
#[test]
fn provenance_names_the_resolved_idna_artifacts() {
let row = PROVENANCE
.lines()
.find(|line| line.contains("UTS #46 mapping"))
.expect("docs/provenance.md has no UTS #46 row");
for token in ["idna", "icu_properties_data"] {
assert!(
row.contains(token),
"the UTS #46 row must name `{token}` — it pins a crate version because `idna` \
publishes no Unicode version.\n\nrow: {row}"
);
}
}