// Copyright 2013-2014 The rust-url developers. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use std::char; use test::TestFn; pub fn collect_tests(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("#") { continue; } // Remove comments let mut 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::>(); 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) } else { "" }; if expected_failure { continue; } let test_name = format!("UTS #46 line {}", i + 1); add_test( test_name, TestFn::dyn_test_fn(move || { let result = 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; } 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() } }; if nv8 == "NV8" { // This result isn't valid under IDNA2008. Skip it return; } assert!( result.is_ok(), "Couldn't parse {} | original: {} | error: {:?}", source, original, result.err() ); let output = result.ok().unwrap(); assert!( output == to_ascii, "result: {} | expected: {} | original: {} | source: {}", output, to_ascii, original, source ); }), ) } } fn unescape(input: &str) -> String { let mut output = String::new(); let mut chars = input.chars(); loop { match chars.next() { None => return output, Some(c) => { if c == '\\' { match chars.next().unwrap() { '\\' => output.push('\\'), 'u' => { let c1 = chars.next().unwrap().to_digit(16).unwrap(); let c2 = chars.next().unwrap().to_digit(16).unwrap(); let c3 = chars.next().unwrap().to_digit(16).unwrap(); let c4 = chars.next().unwrap().to_digit(16).unwrap(); match char::from_u32(((c1 * 16 + c2) * 16 + c3) * 16 + c4) { Some(c) => output.push(c), None => { output .push_str(&format!("\\u{:X}{:X}{:X}{:X}", c1, c2, c3, c4)); } }; } _ => panic!("Invalid test data input"), } } else { output.push(c); } } } } }