ascii_domain

Domains whose labels are only ASCII.
git clone https://git.philomathiclife.com/repos/ascii_domain
Log | Files | Refs | README

tests.rs (14706B)


      1 extern crate alloc;
      2 use super::{Domain, DomainErr, Rfc1123Domain, Rfc1123Err};
      3 use crate::char_set::{ASCII_FIREFOX, ASCII_HYPHEN_DIGITS_LETTERS, AllowedAscii};
      4 use alloc::borrow::ToOwned as _;
      5 use core::cmp::Ordering;
      6 use serde_json as _;
      7 #[test]
      8 fn dom_parse() {
      9     let allowed_ascii = ASCII_FIREFOX;
     10     // Test empty is error.
     11     assert_eq!(
     12         Domain::try_from_bytes("", &allowed_ascii),
     13         Err(DomainErr::Empty)
     14     );
     15     // Test root domain.
     16     assert_eq!(
     17         Domain::try_from_bytes(".", &allowed_ascii),
     18         Err(DomainErr::RootDomain)
     19     );
     20     // Test empty label is error.
     21     assert_eq!(
     22         Domain::try_from_bytes("a..com", &allowed_ascii),
     23         Err(DomainErr::EmptyLabel)
     24     );
     25     assert_eq!(
     26         Domain::try_from_bytes("a..", &allowed_ascii),
     27         Err(DomainErr::EmptyLabel)
     28     );
     29     assert_eq!(
     30         Domain::try_from_bytes("..", &allowed_ascii),
     31         Err(DomainErr::EmptyLabel)
     32     );
     33     // Test label too long.
     34     let val = "www.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com";
     35     // 4 + 64 + 4
     36     assert_eq!(val.len(), 72);
     37     assert_eq!(
     38         Domain::try_from_bytes(val, &allowed_ascii),
     39         Err(DomainErr::LabelLenExceeds63)
     40     );
     41     assert!(
     42         Domain::try_from_bytes(
     43             "www.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com",
     44             &allowed_ascii
     45         )
     46         .is_ok_and(|d| d.len().get() == 71)
     47     );
     48     // Test domain too long.
     49     assert_eq!(
     50         Domain::try_from_bytes(
     51             "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
     52             &allowed_ascii
     53         ),
     54         Err(DomainErr::LenExceeds253(254))
     55     );
     56     assert!(Domain::try_from_bytes("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", &allowed_ascii).is_ok_and(|d| d.len().get() == 253 ));
     57     // Test max labels.
     58     assert_eq!(
     59         Domain::try_from_bytes(
     60             "a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a",
     61             &allowed_ascii
     62         ),
     63         Err(DomainErr::LenExceeds253(255))
     64     );
     65     assert!(Domain::try_from_bytes("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a", &allowed_ascii).is_ok_and(|d| d.iter().count() == 127 && d.len().get() == 253));
     66     assert!(Domain::try_from_bytes("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.", &allowed_ascii).is_ok_and(|d| d.iter().count() == 127 && d.len().get() == 253));
     67     // Test removal of trailing '.'.
     68     assert!(Domain::try_from_bytes("com.", &allowed_ascii).is_ok_and(|d| d.as_str() == "com"));
     69     // Test single label.
     70     assert!(Domain::try_from_bytes("c", &allowed_ascii).is_ok_and(|d| d.as_str() == "c"));
     71     // Test case-insensitivity.
     72     assert!(
     73         Domain::try_from_bytes("wwW.ExAMple.COm", &allowed_ascii).is_ok_and(|d| {
     74             Domain::try_from_bytes("www.example.com", &allowed_ascii)
     75                 .is_ok_and(|d2| d == d2 && d.cmp(&d2) == Ordering::Equal)
     76         })
     77     );
     78     assert!(
     79         Domain::try_from_bytes("ww_W.com", &allowed_ascii).is_ok_and(|d| {
     80             Domain::try_from_bytes("Ww_w.com", &allowed_ascii)
     81                 .is_ok_and(|d2| d == d2 && d.cmp(&d2) == Ordering::Equal)
     82         })
     83     );
     84     // Test valid bytes
     85     let mut input;
     86     let mut counter = 0u8;
     87     for i in 0..=127 {
     88         input = [i];
     89         match i {
     90             b'!'
     91             | b'$'
     92             | b'&'..=b')'
     93             | b'+'..=b'-'
     94             | b'0'..=b'9'
     95             | b';'
     96             | b'='
     97             | b'A'..=b'Z'
     98             | b'_'..=b'{'
     99             | b'}'..=b'~' => {
    100                 counter += 1;
    101                 assert!(
    102                     Domain::try_from_bytes(input, &allowed_ascii)
    103                         .is_ok_and(|d| d.value.len() == 1 && d.value == input)
    104                 );
    105             }
    106             b'.' => {
    107                 let input2 = b"a.";
    108                 assert!(
    109                     Domain::try_from_bytes(input2, &allowed_ascii)
    110                         .is_ok_and(|d| d.len().get() == 1 && d.value == input2)
    111                 );
    112             }
    113             _ => assert_eq!(
    114                 Domain::try_from_bytes(input, &allowed_ascii),
    115                 Err(DomainErr::InvalidByte(i))
    116             ),
    117         }
    118     }
    119     assert_eq!(counter, 78);
    120 }
    121 #[test]
    122 fn dom_iter() {
    123     let allowed_ascii = ASCII_FIREFOX;
    124     assert!(
    125         Domain::try_from_bytes("www.example.com", &allowed_ascii).is_ok_and(|d| {
    126             let mut iter = d.iter();
    127             let Some(l) = iter.next() else {
    128                 return false;
    129             };
    130             if l.value != "com" {
    131                 return false;
    132             }
    133             let Some(l2) = iter.next() else { return false };
    134             if l2.value != "example" {
    135                 return false;
    136             }
    137             let Some(l3) = iter.next() else {
    138                 return false;
    139             };
    140             if l3.value != "www" {
    141                 return false;
    142             }
    143             iter.next().is_none()
    144         })
    145     );
    146     assert!(
    147         Domain::try_from_bytes("www.example.com", &allowed_ascii).is_ok_and(|d| {
    148             let mut iter = d.iter();
    149             let Some(l) = iter.next_back() else {
    150                 return false;
    151             };
    152             if l.value != "www" {
    153                 return false;
    154             }
    155             let Some(l2) = iter.next_back() else {
    156                 return false;
    157             };
    158             if l2.value != "example" {
    159                 return false;
    160             }
    161             let Some(l3) = iter.next_back() else {
    162                 return false;
    163             };
    164             if l3.value != "com" {
    165                 return false;
    166             }
    167             iter.next_back().is_none()
    168         })
    169     );
    170     assert!(
    171         Domain::try_from_bytes("www.example.com", &allowed_ascii).is_ok_and(|d| {
    172             let mut iter = d.iter();
    173             let Some(l) = iter.next_back() else {
    174                 return false;
    175             };
    176             if l.value != "www" {
    177                 return false;
    178             }
    179             let Some(l2) = iter.next() else { return false };
    180             if l2.value != "com" {
    181                 return false;
    182             }
    183             let Some(l3) = iter.next_back() else {
    184                 return false;
    185             };
    186             if l3.value != "example" {
    187                 return false;
    188             }
    189             iter.next().is_none() && iter.next_back().is_none()
    190         })
    191     );
    192 }
    193 #[test]
    194 fn rfc1123() {
    195     assert!(
    196         Domain::try_from_bytes("example.com", &ASCII_HYPHEN_DIGITS_LETTERS)
    197             .is_ok_and(|dom| Rfc1123Domain::try_from(dom)
    198                 .is_ok_and(|rfc_dom| rfc_dom.as_str() == "example.com"))
    199     );
    200     assert!(
    201         AllowedAscii::try_from_unique_ascii(b"exampl!co".to_owned()).is_ok_and(|ascii| {
    202             Domain::try_from_bytes("exampl!e.com", &ascii).is_ok_and(|dom| {
    203                 Rfc1123Domain::try_from(dom)
    204                     .is_err_and(|e| e == Rfc1123Err::DomainErr(DomainErr::InvalidByte(b'!')))
    205             })
    206         })
    207     );
    208     assert!(
    209         Domain::try_from_bytes("example-.com", &ASCII_HYPHEN_DIGITS_LETTERS)
    210             .is_ok_and(|dom| Rfc1123Domain::try_from(dom)
    211                 .is_err_and(|e| e == Rfc1123Err::LabelEndsWithAHyphen))
    212     );
    213     assert!(
    214         Domain::try_from_bytes("-example.com", &ASCII_HYPHEN_DIGITS_LETTERS)
    215             .is_ok_and(|dom| Rfc1123Domain::try_from(dom)
    216                 .is_err_and(|e| e == Rfc1123Err::LabelStartsWithAHyphen))
    217     );
    218     assert!(
    219         Domain::try_from_bytes("example.c1m", &ASCII_HYPHEN_DIGITS_LETTERS).is_ok_and(|dom| {
    220             Rfc1123Domain::try_from(dom).is_err_and(|e| e == Rfc1123Err::InvalidTld)
    221         })
    222     );
    223     assert!(
    224         Domain::try_from_bytes("example.commm", &ASCII_HYPHEN_DIGITS_LETTERS).is_ok_and(|dom| {
    225             Rfc1123Domain::try_from(dom).is_ok_and(|rfc| rfc.is_literal_interpretation())
    226         })
    227     );
    228     assert!(
    229         Domain::try_from_bytes("example.xn--abc", &ASCII_HYPHEN_DIGITS_LETTERS)
    230             .is_ok_and(|dom| Rfc1123Domain::try_from(dom)
    231                 .is_ok_and(|rfc| !rfc.is_literal_interpretation()))
    232     );
    233     assert!(
    234         Domain::try_from_bytes("example.com", &ASCII_HYPHEN_DIGITS_LETTERS).is_ok_and(|dom| {
    235             Rfc1123Domain::try_from(dom).is_ok_and(|rfc| rfc.is_strict_interpretation())
    236         })
    237     );
    238     assert!(
    239         Domain::try_from_bytes("example.comm", &ASCII_HYPHEN_DIGITS_LETTERS).is_ok_and(|dom| {
    240             Rfc1123Domain::try_from(dom).is_ok_and(|rfc| !rfc.is_strict_interpretation())
    241         })
    242     );
    243 }
    244 #[test]
    245 fn tld() {
    246     assert!(
    247         Domain::try_from_bytes("example.com", &ASCII_HYPHEN_DIGITS_LETTERS)
    248             .is_ok_and(|dom| dom.tld().as_str() == "com",)
    249     );
    250 }
    251 #[expect(clippy::cognitive_complexity, reason = "want to test many things")]
    252 #[test]
    253 fn rfc1123_parse() {
    254     // Test empty is error.
    255     assert_eq!(
    256         Rfc1123Domain::try_from_bytes(""),
    257         Err(Rfc1123Err::DomainErr(DomainErr::Empty))
    258     );
    259     // Test root domain.
    260     assert_eq!(
    261         Rfc1123Domain::try_from_bytes("."),
    262         Err(Rfc1123Err::DomainErr(DomainErr::RootDomain))
    263     );
    264     // Test empty label is error.
    265     assert_eq!(
    266         Rfc1123Domain::try_from_bytes("a..com"),
    267         Err(Rfc1123Err::DomainErr(DomainErr::EmptyLabel))
    268     );
    269     assert_eq!(
    270         Rfc1123Domain::try_from_bytes("a.."),
    271         Err(Rfc1123Err::DomainErr(DomainErr::EmptyLabel))
    272     );
    273     assert_eq!(
    274         Rfc1123Domain::try_from_bytes(".."),
    275         Err(Rfc1123Err::DomainErr(DomainErr::EmptyLabel))
    276     );
    277     // Test label too long.
    278     let val = "www.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com";
    279     // 4 + 64 + 4
    280     assert_eq!(val.len(), 72);
    281     assert_eq!(
    282         Rfc1123Domain::try_from_bytes(val),
    283         Err(Rfc1123Err::DomainErr(DomainErr::LabelLenExceeds63),)
    284     );
    285     assert!(
    286         Rfc1123Domain::try_from_bytes(
    287             "www.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com",
    288         )
    289         .is_ok_and(|d| d.len().get() == 71)
    290     );
    291     // Test domain too long.
    292     assert_eq!(
    293         Rfc1123Domain::try_from_bytes(
    294             "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
    295         ),
    296         Err(Rfc1123Err::DomainErr(DomainErr::LenExceeds253(254)))
    297     );
    298     assert!(Rfc1123Domain::try_from_bytes("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").is_ok_and(|d| d.len().get() == 253 ));
    299     // Test max labels.
    300     assert_eq!(
    301         Rfc1123Domain::try_from_bytes(
    302             "a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a"
    303         ),
    304         Err(Rfc1123Err::DomainErr(DomainErr::LenExceeds253(255)))
    305     );
    306     assert!(Rfc1123Domain::try_from_bytes("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a").is_ok_and(|d| d.iter().count() == 127 && d.len().get() == 253));
    307     assert!(Rfc1123Domain::try_from_bytes("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.").is_ok_and(|d| d.iter().count() == 127 && d.len().get() == 253));
    308     // Test removal of trailing '.'.
    309     assert!(Rfc1123Domain::try_from_bytes("com.").is_ok_and(|d| d.as_str() == "com"));
    310     // Test single label.
    311     assert!(Rfc1123Domain::try_from_bytes("c").is_ok_and(|d| *d.as_inner() == "c"));
    312     // Test ends with hyphen.
    313     assert_eq!(
    314         Rfc1123Domain::try_from_bytes("-"),
    315         Err(Rfc1123Err::LabelEndsWithAHyphen)
    316     );
    317     assert_eq!(
    318         Rfc1123Domain::try_from_bytes("-."),
    319         Err(Rfc1123Err::LabelEndsWithAHyphen)
    320     );
    321     assert_eq!(
    322         Rfc1123Domain::try_from_bytes("a.com.-"),
    323         Err(Rfc1123Err::LabelEndsWithAHyphen)
    324     );
    325     assert_eq!(
    326         Rfc1123Domain::try_from_bytes("a.com-"),
    327         Err(Rfc1123Err::LabelEndsWithAHyphen)
    328     );
    329     assert_eq!(
    330         Rfc1123Domain::try_from_bytes("a-.com"),
    331         Err(Rfc1123Err::LabelEndsWithAHyphen)
    332     );
    333     // Test starts with hyphen.
    334     assert_eq!(
    335         Rfc1123Domain::try_from_bytes("a.-com"),
    336         Err(Rfc1123Err::LabelStartsWithAHyphen)
    337     );
    338     assert_eq!(
    339         Rfc1123Domain::try_from_bytes("-a.com"),
    340         Err(Rfc1123Err::LabelStartsWithAHyphen)
    341     );
    342     // Test case-insensitivity.
    343     assert!(
    344         Rfc1123Domain::try_from_bytes("wwW.ExAMple.COm").is_ok_and(|d| {
    345             Rfc1123Domain::try_from_bytes("www.example.com")
    346                 .is_ok_and(|d2| d == d2 && d.cmp(&d2) == Ordering::Equal)
    347         })
    348     );
    349     assert!(Rfc1123Domain::try_from_bytes("ww-W.com").is_ok_and(|d| {
    350         Rfc1123Domain::try_from_bytes("Ww-w.com")
    351             .is_ok_and(|d2| d.domain() == d2.domain() && d.cmp(&d2) == Ordering::Equal)
    352     }));
    353     assert_eq!(
    354         Rfc1123Domain::try_from_bytes("1.1.1.1"),
    355         Err(Rfc1123Err::InvalidTld)
    356     );
    357 }