idna.rs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. extern crate url;
  2. use std::char;
  3. use url::idna;
  4. #[test]
  5. fn test_uts46() {
  6. // http://www.unicode.org/Public/idna/latest/IdnaTest.txt
  7. for line in include_str!("IdnaTest.txt").lines() {
  8. if line == "" || line.starts_with("#") {
  9. continue
  10. }
  11. // Remove comments
  12. let mut line = match line.find("#") {
  13. Some(index) => &line[0..index],
  14. None => line
  15. };
  16. let mut expected_failure = false;
  17. if line.starts_with("XFAIL") {
  18. expected_failure = true;
  19. line = &line[5..line.len()];
  20. };
  21. let mut pieces = line.split(';').map(|x| x.trim()).collect::<Vec<&str>>();
  22. let test_type = pieces.remove(0);
  23. let original = pieces.remove(0);
  24. let source = unescape(original);
  25. let to_unicode = pieces.remove(0);
  26. let to_ascii = pieces.remove(0);
  27. let _nv8 = if pieces.len() > 0 { pieces.remove(0) } else { "" };
  28. if expected_failure {
  29. continue;
  30. }
  31. let result = idna::uts46_to_ascii(&source, idna::Uts46Flags {
  32. use_std3_ascii_rules: true,
  33. transitional_processing: test_type == "T",
  34. verify_dns_length: true,
  35. });
  36. if to_ascii.starts_with("[") {
  37. if to_ascii.starts_with("[C") {
  38. // http://unicode.org/reports/tr46/#Deviations
  39. // applications that perform IDNA2008 lookup are not required to check for these contexts
  40. continue;
  41. }
  42. let res = result.ok();
  43. assert!(res == None, "Expected error. result: {} | original: {} | source: {}", res.unwrap(), original, source);
  44. continue;
  45. }
  46. let to_ascii = if to_ascii.len() > 0 {
  47. to_ascii.to_string()
  48. } else {
  49. if to_unicode.len() > 0 {
  50. to_unicode.to_string()
  51. } else {
  52. source.clone()
  53. }
  54. };
  55. if _nv8 == "NV8" {
  56. // This result isn't valid under IDNA2008. Skip it
  57. continue;
  58. }
  59. assert!(result.is_ok(), "Couldn't parse {} | original: {} | error: {:?}", source, original, result.err());
  60. let output = result.ok().unwrap();
  61. assert!(output == to_ascii, "result: {} | expected: {} | original: {} | source: {}", output, to_ascii, original, source);
  62. }
  63. }
  64. fn unescape(input: &str) -> String {
  65. let mut output = String::new();
  66. let mut chars = input.chars();
  67. loop {
  68. match chars.next() {
  69. None => return output,
  70. Some(c) =>
  71. if c == '\\' {
  72. match chars.next().unwrap() {
  73. '\\' => output.push('\\'),
  74. 'u' => {
  75. let c1 = chars.next().unwrap().to_digit(16).unwrap();
  76. let c2 = chars.next().unwrap().to_digit(16).unwrap();
  77. let c3 = chars.next().unwrap().to_digit(16).unwrap();
  78. let c4 = chars.next().unwrap().to_digit(16).unwrap();
  79. match char::from_u32((((c1 * 16 + c2) * 16 + c3) * 16 + c4))
  80. {
  81. Some(c) => output.push(c),
  82. None => { output.push_str(&format!("\\u{:X}{:X}{:X}{:X}",c1,c2,c3,c4)); }
  83. };
  84. }
  85. _ => panic!("Invalid test data input"),
  86. }
  87. } else {
  88. output.push(c);
  89. }
  90. }
  91. }
  92. }