| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- // Copyright 2013-2014 The rust-url developers.
- //
- // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
- // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
- // <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<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("#") {
- 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::<Vec<&str>>();
- 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);
- }
- }
- }
- }
- }
|