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