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 }