]> git.proxmox.com Git - rustc.git/blobdiff - vendor/idna/tests/uts46.rs
Merge tag 'debian/1.52.1+dfsg1-1_exp2' into proxmox/buster
[rustc.git] / vendor / idna / tests / uts46.rs
index b3a5ff334857c800b10e9c01de7b68df4db3d49a..72b5bcec7d8b2e2c3bc7acf5baa0d6345d22b5f5 100644 (file)
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use crate::test::TestFn;
 use std::char;
-use test::TestFn;
+
+use idna::Errors;
 
 pub fn collect_tests<F: FnMut(String, TestFn)>(add_test: &mut F) {
-    // http://www.unicode.org/Public/idna/latest/IdnaTest.txt
-    for (i, line) in include_str!("IdnaTest.txt").lines().enumerate() {
-        if line == "" || line.starts_with("#") {
+    // https://www.unicode.org/Public/idna/13.0.0/IdnaTestV2.txt
+    for (i, line) in include_str!("IdnaTestV2.txt").lines().enumerate() {
+        if line.is_empty() || line.starts_with('#') {
             continue;
         }
+
         // Remove comments
-        let mut line = match line.find("#") {
+        let line = match line.find('#') {
             Some(index) => &line[0..index],
             None => line,
         };
 
-        let mut expected_failure = false;
-        if line.starts_with("XFAIL") {
-            expected_failure = true;
-            line = &line[5..line.len()];
-        };
-
         let mut pieces = line.split(';').map(|x| x.trim()).collect::<Vec<&str>>();
+        let source = unescape(&pieces.remove(0));
 
-        let test_type = pieces.remove(0);
-        let original = pieces.remove(0);
-        let source = unescape(original);
-        let to_unicode = pieces.remove(0);
-        let to_ascii = pieces.remove(0);
-        let nv8 = if pieces.len() > 0 {
-            pieces.remove(0)
+        // ToUnicode
+        let mut to_unicode = unescape(&pieces.remove(0));
+        if to_unicode.is_empty() {
+            to_unicode = source.clone();
+        }
+        let to_unicode_status = status(pieces.remove(0));
+
+        // ToAsciiN
+        let to_ascii_n = pieces.remove(0);
+        let to_ascii_n = if to_ascii_n.is_empty() {
+            to_unicode.clone()
+        } else {
+            to_ascii_n.to_owned()
+        };
+        let to_ascii_n_status = pieces.remove(0);
+        let to_ascii_n_status = if to_ascii_n_status.is_empty() {
+            to_unicode_status.clone()
         } else {
-            ""
+            status(to_ascii_n_status)
         };
 
-        if expected_failure {
-            continue;
-        }
+        // ToAsciiT
+        let to_ascii_t = pieces.remove(0);
+        let to_ascii_t = if to_ascii_t.is_empty() {
+            to_ascii_n.clone()
+        } else {
+            to_ascii_t.to_owned()
+        };
+        let to_ascii_t_status = pieces.remove(0);
+        let to_ascii_t_status = if to_ascii_t_status.is_empty() {
+            to_ascii_n_status.clone()
+        } else {
+            status(to_ascii_t_status)
+        };
 
         let test_name = format!("UTS #46 line {}", i + 1);
         add_test(
             test_name,
             TestFn::dyn_test_fn(move || {
-                let result = idna::Config::default()
+                let config = idna::Config::default()
                     .use_std3_ascii_rules(true)
                     .verify_dns_length(true)
-                    .check_hyphens(true)
-                    .transitional_processing(test_type == "T")
-                    .to_ascii(&source);
-
-                if to_ascii.starts_with("[") {
-                    if to_ascii.starts_with("[C") {
-                        // http://unicode.org/reports/tr46/#Deviations
-                        // applications that perform IDNA2008 lookup are not required to check
-                        // for these contexts
-                        return;
-                    }
-                    if to_ascii == "[V2]" {
-                        // Everybody ignores V2
-                        // https://github.com/servo/rust-url/pull/240
-                        // https://github.com/whatwg/url/issues/53#issuecomment-181528158
-                        // http://www.unicode.org/review/pri317/
-                        return;
-                    }
-                    let res = result.ok();
-                    assert!(
-                        res == None,
-                        "Expected error. result: {} | original: {} | source: {}",
-                        res.unwrap(),
-                        original,
-                        source
-                    );
-                    return;
-                }
+                    .check_hyphens(true);
 
-                let to_ascii = if to_ascii.len() > 0 {
-                    to_ascii.to_string()
-                } else {
-                    if to_unicode.len() > 0 {
-                        to_unicode.to_string()
-                    } else {
-                        source.clone()
-                    }
-                };
+                // http://unicode.org/reports/tr46/#Deviations
+                // applications that perform IDNA2008 lookup are not required to check
+                // for these contexts, so we skip all tests annotated with C*
 
-                if nv8 == "NV8" {
-                    // This result isn't valid under IDNA2008. Skip it
-                    return;
-                }
+                // Everybody ignores V2
+                // https://github.com/servo/rust-url/pull/240
+                // https://github.com/whatwg/url/issues/53#issuecomment-181528158
+                // http://www.unicode.org/review/pri317/
 
-                assert!(
-                    result.is_ok(),
-                    "Couldn't parse {} | original: {} | error: {:?}",
-                    source,
-                    original,
-                    result.err()
+                // "The special error codes X3 and X4_2 are now returned where a toASCII error code
+                // was formerly being generated in toUnicode due to an empty label."
+                // This is not implemented yet, so we skip toUnicode X4_2 tests for now, too.
+
+                let (to_unicode_value, to_unicode_result) =
+                    config.transitional_processing(false).to_unicode(&source);
+                let to_unicode_result = to_unicode_result.map(|()| to_unicode_value);
+                check(
+                    &source,
+                    (&to_unicode, &to_unicode_status),
+                    to_unicode_result,
+                    |e| e.starts_with('C') || e == "V2" || e == "X4_2",
                 );
-                let output = result.ok().unwrap();
-                assert!(
-                    output == to_ascii,
-                    "result: {} | expected: {} | original: {} | source: {}",
-                    output,
-                    to_ascii,
-                    original,
-                    source
+
+                let to_ascii_n_result = config.transitional_processing(false).to_ascii(&source);
+                check(
+                    &source,
+                    (&to_ascii_n, &to_ascii_n_status),
+                    to_ascii_n_result,
+                    |e| e.starts_with('C') || e == "V2",
+                );
+
+                let to_ascii_t_result = config.transitional_processing(true).to_ascii(&source);
+                check(
+                    &source,
+                    (&to_ascii_t, &to_ascii_t_status),
+                    to_ascii_t_result,
+                    |e| e.starts_with('C') || e == "V2",
                 );
             }),
         )
     }
 }
 
+#[allow(clippy::redundant_clone)]
+fn check<F>(source: &str, expected: (&str, &[&str]), actual: Result<String, Errors>, ignore: F)
+where
+    F: Fn(&str) -> bool,
+{
+    if !expected.1.is_empty() {
+        if !expected.1.iter().copied().any(ignore) {
+            let res = actual.ok();
+            assert_eq!(
+                res.clone(),
+                None,
+                "Expected error {:?}. result: {} | source: {}",
+                expected.1,
+                res.unwrap(),
+                source,
+            );
+        }
+    } else {
+        assert!(
+            actual.is_ok(),
+            "Couldn't parse {} | error: {:?}",
+            source,
+            actual.err().unwrap(),
+        );
+        assert_eq!(actual.unwrap(), expected.0, "source: {}", source);
+    }
+}
+
 fn unescape(input: &str) -> String {
     let mut output = String::new();
     let mut chars = input.chars();
@@ -148,3 +174,20 @@ fn unescape(input: &str) -> String {
         }
     }
 }
+
+fn status(status: &str) -> Vec<&str> {
+    if status.is_empty() || status == "[]" {
+        return Vec::new();
+    }
+
+    let mut result = status.split(", ").collect::<Vec<_>>();
+    assert!(result[0].starts_with('['));
+    result[0] = &result[0][1..];
+
+    let idx = result.len() - 1;
+    let last = &mut result[idx];
+    assert!(last.ends_with(']'));
+    *last = &last[..last.len() - 1];
+
+    result
+}