uts46.rs 3.8 KB

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