use super::*;
#[test]
fn accepts_assigned() {
for code in ["US", "DE", "JP", "GB", "TW", "XK", "OM", "QA"] {
assert!(is_valid_region(code), "{code} should be accepted");
}
}
#[test]
fn accepts_user_reserved() {
for code in ["AA", "QM", "QN", "QZ", "XA", "XK", "XL", "XX", "XZ", "ZZ"] {
assert!(is_valid_region(code), "{code} should be accepted");
}
}
#[test]
fn rejects_unassigned_uppercase() {
for code in ["OO", "JJ", "BX", "WW", "OP", "OZ"] {
assert!(!is_valid_region(code), "{code} should be rejected");
}
}
#[test]
fn rejects_malformed() {
for code in [
"", "U", "USA", "us", "Us", "uS", "U S", "U/", "/U", "U\0", "U\n", "\0\0", "Ü1", "1U",
"12", "U-",
] {
assert!(!is_valid_region(code), "{code:?} should be rejected");
}
}
#[test]
fn parse_normalizes_case_and_whitespace_into_one_value() {
let canonical = Region::parse("US").expect("US is assigned");
for spelling in ["us", " US ", "\tuS\n", "Us"] {
assert_eq!(
Region::parse(spelling),
Some(canonical),
"{spelling:?} must normalize to the same value as \"US\""
);
}
assert_eq!(canonical.as_str(), "US");
assert_eq!(canonical.to_string(), "US");
}
#[test]
fn debug_renders_the_code_not_the_bytes() {
let region = Region::parse("US").expect("US is assigned");
assert_eq!(format!("{region:?}"), r#"Region("US")"#);
assert_eq!(format!("{:?}", Some(region)), r#"Some(Region("US"))"#);
}
#[test]
fn every_accepted_code_round_trips_and_is_never_empty() {
let mut accepted = 0usize;
for a in b'A'..=b'Z' {
for b in b'A'..=b'Z' {
let code = String::from_utf8(vec![a, b]).expect("ASCII by construction");
if !is_valid_region(&code) {
continue;
}
accepted += 1;
let region = Region::parse(&code).expect("the predicate accepted it");
assert_eq!(
region.as_str(),
code,
"as_str must be total — never the empty fallback"
);
}
}
assert!(
accepted > 240,
"the allowlist collapsed to {accepted} codes; ISO 3166-1 assigns ~250"
);
}
#[test]
fn parse_agrees_with_is_valid_region() {
for code in ["US", "DE", "XK", "AA", "QZ", "ZZ"] {
assert!(Region::parse(code).is_some(), "{code} should parse");
}
for code in ["OO", "JJ", "", "U", "USA", "U/", "U\0", "Ü1", "12"] {
assert!(Region::parse(code).is_none(), "{code:?} should not parse");
}
}
#[test]
fn construction_errors_do_not_echo_the_input() {
let from_str = "U\n/evil".parse::<Region>().expect_err("must reject");
let msg = from_str.to_string();
assert!(
!msg.contains("evil"),
"input leaked into the message: {msg}"
);
assert!(msg.contains("ISO 3166-1"), "{msg}");
let de = serde_json::from_str::<Region>("\"U\\n/evil\"").expect_err("must reject");
let msg = de.to_string();
assert!(
!msg.contains("evil"),
"input leaked through the deserializer: {msg}"
);
assert!(msg.contains("ISO 3166-1"), "{msg}");
}
#[test]
fn serializes_as_a_plain_string() {
let region = Region::parse("DE").expect("DE is assigned");
let json = serde_json::to_string(®ion).expect("serialize");
assert_eq!(json, "\"DE\"");
assert_eq!(
serde_json::from_str::<Region>(&json).expect("round-trip"),
region
);
}
#[test]
fn deserialize_rejects_an_invalid_code() {
assert!(serde_json::from_str::<Region>("\"OO\"").is_err());
assert!(serde_json::from_str::<Region>("\"USA\"").is_err());
assert_eq!(
serde_json::from_str::<Region>("\"de\"").expect("normalizes on the way in"),
Region::parse("DE").expect("DE is assigned")
);
}