1 use assert_matches::assert_matches;
2 use unicode_normalization::char::is_combining_mark;
3
4 /// https://github.com/servo/rust-url/issues/373
5 #[test]
test_punycode_prefix_with_length_check()6 fn test_punycode_prefix_with_length_check() {
7 let config = idna::Config::default()
8 .verify_dns_length(true)
9 .check_hyphens(true)
10 .use_std3_ascii_rules(true);
11
12 assert!(config.to_ascii("xn--").is_err());
13 assert!(config.to_ascii("xn---").is_err());
14 assert!(config.to_ascii("xn-----").is_err());
15 assert!(config.to_ascii("xn--.").is_err());
16 assert!(config.to_ascii("xn--...").is_err());
17 assert!(config.to_ascii(".xn--").is_err());
18 assert!(config.to_ascii("...xn--").is_err());
19 assert!(config.to_ascii("xn--.xn--").is_err());
20 assert!(config.to_ascii("xn--.example.org").is_err());
21 }
22
23 /// https://github.com/servo/rust-url/issues/373
24 #[test]
test_punycode_prefix_without_length_check()25 fn test_punycode_prefix_without_length_check() {
26 let config = idna::Config::default()
27 .verify_dns_length(false)
28 .check_hyphens(true)
29 .use_std3_ascii_rules(true);
30
31 assert_eq!(config.to_ascii("xn--").unwrap(), "");
32 assert!(config.to_ascii("xn---").is_err());
33 assert!(config.to_ascii("xn-----").is_err());
34 assert_eq!(config.to_ascii("xn--.").unwrap(), ".");
35 assert_eq!(config.to_ascii("xn--...").unwrap(), "...");
36 assert_eq!(config.to_ascii(".xn--").unwrap(), ".");
37 assert_eq!(config.to_ascii("...xn--").unwrap(), "...");
38 assert_eq!(config.to_ascii("xn--.xn--").unwrap(), ".");
39 assert_eq!(config.to_ascii("xn--.example.org").unwrap(), ".example.org");
40 }
41
42 // http://www.unicode.org/reports/tr46/#Table_Example_Processing
43 #[test]
test_examples()44 fn test_examples() {
45 let mut codec = idna::Idna::default();
46 let mut out = String::new();
47
48 assert_matches!(codec.to_unicode("Bloß.de", &mut out), Ok(()));
49 assert_eq!(out, "bloß.de");
50
51 out.clear();
52 assert_matches!(codec.to_unicode("xn--blo-7ka.de", &mut out), Ok(()));
53 assert_eq!(out, "bloß.de");
54
55 out.clear();
56 assert_matches!(codec.to_unicode("u\u{308}.com", &mut out), Ok(()));
57 assert_eq!(out, "ü.com");
58
59 out.clear();
60 assert_matches!(codec.to_unicode("xn--tda.com", &mut out), Ok(()));
61 assert_eq!(out, "ü.com");
62
63 out.clear();
64 assert_matches!(codec.to_unicode("xn--u-ccb.com", &mut out), Err(_));
65
66 out.clear();
67 assert_matches!(codec.to_unicode("a⒈com", &mut out), Err(_));
68
69 out.clear();
70 assert_matches!(codec.to_unicode("xn--a-ecp.ru", &mut out), Err(_));
71
72 out.clear();
73 assert_matches!(codec.to_unicode("xn--0.pt", &mut out), Err(_));
74
75 out.clear();
76 assert_matches!(codec.to_unicode("日本語。JP", &mut out), Ok(()));
77 assert_eq!(out, "日本語.jp");
78
79 out.clear();
80 assert_matches!(codec.to_unicode("☕.us", &mut out), Ok(()));
81 assert_eq!(out, "☕.us");
82 }
83
84 #[test]
test_v5()85 fn test_v5() {
86 let config = idna::Config::default()
87 .verify_dns_length(true)
88 .use_std3_ascii_rules(true);
89
90 // IdnaTest:784 蔏。
91 assert!(is_combining_mark('\u{11C3A}'));
92 assert!(config.to_ascii("\u{11C3A}").is_err());
93 assert!(config.to_ascii("\u{850f}.\u{11C3A}").is_err());
94 assert!(config.to_ascii("\u{850f}\u{ff61}\u{11C3A}").is_err());
95 }
96
97 #[test]
test_v8_bidi_rules()98 fn test_v8_bidi_rules() {
99 let config = idna::Config::default()
100 .verify_dns_length(true)
101 .use_std3_ascii_rules(true);
102
103 assert_eq!(config.to_ascii("abc").unwrap(), "abc");
104 assert_eq!(config.to_ascii("123").unwrap(), "123");
105 assert_eq!(config.to_ascii("אבּג").unwrap(), "xn--kdb3bdf");
106 assert_eq!(config.to_ascii("ابج").unwrap(), "xn--mgbcm");
107 assert_eq!(config.to_ascii("abc.ابج").unwrap(), "abc.xn--mgbcm");
108 assert_eq!(config.to_ascii("אבּג.ابج").unwrap(), "xn--kdb3bdf.xn--mgbcm");
109
110 // Bidi domain names cannot start with digits
111 assert!(config.to_ascii("0a.\u{05D0}").is_err());
112 assert!(config.to_ascii("0à.\u{05D0}").is_err());
113
114 // Bidi chars may be punycode-encoded
115 assert!(config.to_ascii("xn--0ca24w").is_err());
116 }
117
118 #[test]
emoji_domains()119 fn emoji_domains() {
120 // HOT BEVERAGE is allowed here...
121 let config = idna::Config::default()
122 .verify_dns_length(true)
123 .use_std3_ascii_rules(true);
124 assert_eq!(config.to_ascii("☕.com").unwrap(), "xn--53h.com");
125
126 // ... but not here
127 let config = idna::Config::default()
128 .verify_dns_length(true)
129 .use_std3_ascii_rules(true)
130 .use_idna_2008_rules(true);
131 let error = format!("{:?}", config.to_ascii("☕.com").unwrap_err());
132 assert!(error.contains("disallowed_in_idna_2008"));
133 }
134
135 #[test]
unicode_before_delimiter()136 fn unicode_before_delimiter() {
137 let config = idna::Config::default();
138 assert!(config.to_ascii("xn--f\u{34a}-PTP").is_err());
139 }
140