You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

249 lines
9.3 KiB

  1. // Copyright 2015 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package japanese
  5. import (
  6. "fmt"
  7. "strings"
  8. "testing"
  9. "golang.org/x/text/encoding"
  10. "golang.org/x/text/encoding/internal"
  11. "golang.org/x/text/encoding/internal/enctest"
  12. "golang.org/x/text/transform"
  13. )
  14. func dec(e encoding.Encoding) (dir string, t transform.Transformer, err error) {
  15. return "Decode", e.NewDecoder(), nil
  16. }
  17. func enc(e encoding.Encoding) (dir string, t transform.Transformer, err error) {
  18. return "Encode", e.NewEncoder(), internal.ErrASCIIReplacement
  19. }
  20. func TestNonRepertoire(t *testing.T) {
  21. // Pick n to cause the destination buffer in transform.String to overflow.
  22. const n = 100
  23. long := strings.Repeat(".", n)
  24. testCases := []struct {
  25. init func(e encoding.Encoding) (string, transform.Transformer, error)
  26. e encoding.Encoding
  27. src, want string
  28. }{
  29. {enc, EUCJP, "갂", ""},
  30. {enc, EUCJP, "a갂", "a"},
  31. {enc, EUCJP, "丌갂", "\x8f\xb0\xa4"},
  32. {enc, ISO2022JP, "갂", ""},
  33. {enc, ISO2022JP, "a갂", "a"},
  34. {enc, ISO2022JP, "朗갂", "\x1b$BzF\x1b(B"}, // switch back to ASCII mode at end
  35. {enc, ShiftJIS, "갂", ""},
  36. {enc, ShiftJIS, "a갂", "a"},
  37. {enc, ShiftJIS, "\u2190갂", "\x81\xa9"},
  38. // Continue correctly after errors
  39. {dec, EUCJP, "\x8e\xa0", "\ufffd\ufffd"},
  40. {dec, EUCJP, "\x8e\xe0", "\ufffd"},
  41. {dec, EUCJP, "\x8e\xff", "\ufffd\ufffd"},
  42. {dec, EUCJP, "\x8ea", "\ufffda"},
  43. {dec, EUCJP, "\x8f\xa0", "\ufffd\ufffd"},
  44. {dec, EUCJP, "\x8f\xa1\xa0", "\ufffd\ufffd"},
  45. {dec, EUCJP, "\x8f\xa1a", "\ufffda"},
  46. {dec, EUCJP, "\x8f\xa1a", "\ufffda"},
  47. {dec, EUCJP, "\x8f\xa1a", "\ufffda"},
  48. {dec, EUCJP, "\x8f\xa2\xa2", "\ufffd"},
  49. {dec, EUCJP, "\xfe", "\ufffd"},
  50. {dec, EUCJP, "\xfe\xfc", "\ufffd"},
  51. {dec, EUCJP, "\xfe\xff", "\ufffd\ufffd"},
  52. // Correct handling of end of source
  53. {dec, EUCJP, strings.Repeat("\x8e", n), strings.Repeat("\ufffd", n)},
  54. {dec, EUCJP, strings.Repeat("\x8f", n), strings.Repeat("\ufffd", n)},
  55. {dec, EUCJP, strings.Repeat("\x8f\xa0", n), strings.Repeat("\ufffd", 2*n)},
  56. {dec, EUCJP, "a" + strings.Repeat("\x8f\xa1", n), "a" + strings.Repeat("\ufffd", n)},
  57. {dec, EUCJP, "a" + strings.Repeat("\x8f\xa1\xff", n), "a" + strings.Repeat("\ufffd", 2*n)},
  58. // Continue correctly after errors
  59. {dec, ShiftJIS, "\x80", "\u0080"}, // It's what the spec says.
  60. {dec, ShiftJIS, "\x81", "\ufffd"},
  61. {dec, ShiftJIS, "\x81\x7f", "\ufffd\u007f"},
  62. {dec, ShiftJIS, "\xe0", "\ufffd"},
  63. {dec, ShiftJIS, "\xe0\x39", "\ufffd\u0039"},
  64. {dec, ShiftJIS, "\xe0\x9f", "燹"},
  65. {dec, ShiftJIS, "\xe0\xfd", "\ufffd"},
  66. {dec, ShiftJIS, "\xef\xfc", "\ufffd"},
  67. {dec, ShiftJIS, "\xfc\xfc", "\ufffd"},
  68. {dec, ShiftJIS, "\xfc\xfd", "\ufffd"},
  69. {dec, ShiftJIS, "\xfdaa", "\ufffdaa"},
  70. {dec, ShiftJIS, strings.Repeat("\x81\x81", n), strings.Repeat("=", n)},
  71. {dec, ShiftJIS, strings.Repeat("\xe0\xfd", n), strings.Repeat("\ufffd", n)},
  72. {dec, ShiftJIS, "a" + strings.Repeat("\xe0\xfd", n), "a" + strings.Repeat("\ufffd", n)},
  73. {dec, ISO2022JP, "\x1b$", "\ufffd$"},
  74. {dec, ISO2022JP, "\x1b(", "\ufffd("},
  75. {dec, ISO2022JP, "\x1b@", "\ufffd@"},
  76. {dec, ISO2022JP, "\x1bZ", "\ufffdZ"},
  77. // incomplete escapes
  78. {dec, ISO2022JP, "\x1b$", "\ufffd$"},
  79. {dec, ISO2022JP, "\x1b$J.", "\ufffd$J."}, // illegal
  80. {dec, ISO2022JP, "\x1b$B.", "\ufffd"}, // JIS208
  81. {dec, ISO2022JP, "\x1b$(", "\ufffd$("}, // JIS212
  82. {dec, ISO2022JP, "\x1b$(..", "\ufffd$(.."}, // JIS212
  83. {dec, ISO2022JP, "\x1b$(" + long, "\ufffd$(" + long}, // JIS212
  84. {dec, ISO2022JP, "\x1b$(D.", "\ufffd"}, // JIS212
  85. {dec, ISO2022JP, "\x1b$(D..", "\ufffd"}, // JIS212
  86. {dec, ISO2022JP, "\x1b$(D...", "\ufffd\ufffd"}, // JIS212
  87. {dec, ISO2022JP, "\x1b(B.", "."}, // ascii
  88. {dec, ISO2022JP, "\x1b(B..", ".."}, // ascii
  89. {dec, ISO2022JP, "\x1b(J.", "."}, // roman
  90. {dec, ISO2022JP, "\x1b(J..", ".."}, // roman
  91. {dec, ISO2022JP, "\x1b(I\x20", "\ufffd"}, // katakana
  92. {dec, ISO2022JP, "\x1b(I\x20\x20", "\ufffd\ufffd"}, // katakana
  93. // recover to same state
  94. {dec, ISO2022JP, "\x1b(B\x1b.", "\ufffd."},
  95. {dec, ISO2022JP, "\x1b(I\x1b.", "\ufffdョ"},
  96. {dec, ISO2022JP, "\x1b(I\x1b$.", "\ufffd、ョ"},
  97. {dec, ISO2022JP, "\x1b(I\x1b(.", "\ufffdィョ"},
  98. {dec, ISO2022JP, "\x1b$B\x7e\x7e", "\ufffd"},
  99. {dec, ISO2022JP, "\x1b$@\x0a.", "\x0a."},
  100. {dec, ISO2022JP, "\x1b$B\x0a.", "\x0a."},
  101. {dec, ISO2022JP, "\x1b$(D\x0a.", "\x0a."},
  102. {dec, ISO2022JP, "\x1b$(D\x7e\x7e", "\ufffd"},
  103. {dec, ISO2022JP, "\x80", "\ufffd"},
  104. // TODO: according to https://encoding.spec.whatwg.org/#iso-2022-jp,
  105. // these should all be correct.
  106. // {dec, ISO2022JP, "\x1b(B\x0E", "\ufffd"},
  107. // {dec, ISO2022JP, "\x1b(B\x0F", "\ufffd"},
  108. {dec, ISO2022JP, "\x1b(B\x5C", "\u005C"},
  109. {dec, ISO2022JP, "\x1b(B\x7E", "\u007E"},
  110. // {dec, ISO2022JP, "\x1b(J\x0E", "\ufffd"},
  111. // {dec, ISO2022JP, "\x1b(J\x0F", "\ufffd"},
  112. // {dec, ISO2022JP, "\x1b(J\x5C", "\u00A5"},
  113. // {dec, ISO2022JP, "\x1b(J\x7E", "\u203E"},
  114. }
  115. for _, tc := range testCases {
  116. dir, tr, wantErr := tc.init(tc.e)
  117. t.Run(fmt.Sprintf("%s/%v/%q", dir, tc.e, tc.src), func(t *testing.T) {
  118. dst := make([]byte, 100000)
  119. src := []byte(tc.src)
  120. for i := 0; i <= len(tc.src); i++ {
  121. nDst, nSrc, err := tr.Transform(dst, src[:i], false)
  122. if err != nil && err != transform.ErrShortSrc && err != wantErr {
  123. t.Fatalf("error on first call to Transform: %v", err)
  124. }
  125. n, _, err := tr.Transform(dst[nDst:], src[nSrc:], true)
  126. nDst += n
  127. if err != wantErr {
  128. t.Fatalf("(%q|%q): got %v; want %v", tc.src[:i], tc.src[i:], err, wantErr)
  129. }
  130. if got := string(dst[:nDst]); got != tc.want {
  131. t.Errorf("(%q|%q):\ngot %q\nwant %q", tc.src[:i], tc.src[i:], got, tc.want)
  132. }
  133. }
  134. })
  135. }
  136. }
  137. func TestCorrect(t *testing.T) {
  138. testCases := []struct {
  139. init func(e encoding.Encoding) (string, transform.Transformer, error)
  140. e encoding.Encoding
  141. src, want string
  142. }{
  143. {dec, ShiftJIS, "\x9f\xfc", "滌"},
  144. {dec, ShiftJIS, "\xfb\xfc", "髙"},
  145. {dec, ShiftJIS, "\xfa\xb1", "﨑"},
  146. {enc, ShiftJIS, "滌", "\x9f\xfc"},
  147. {enc, ShiftJIS, "﨑", "\xed\x95"},
  148. }
  149. for _, tc := range testCases {
  150. dir, tr, _ := tc.init(tc.e)
  151. dst, _, err := transform.String(tr, tc.src)
  152. if err != nil {
  153. t.Errorf("%s %v(%q): got %v; want %v", dir, tc.e, tc.src, err, nil)
  154. }
  155. if got := string(dst); got != tc.want {
  156. t.Errorf("%s %v(%q):\ngot %q\nwant %q", dir, tc.e, tc.src, got, tc.want)
  157. }
  158. }
  159. }
  160. func TestBasics(t *testing.T) {
  161. // The encoded forms can be verified by the iconv program:
  162. // $ echo 月日は百代 | iconv -f UTF-8 -t SHIFT-JIS | xxd
  163. testCases := []struct {
  164. e encoding.Encoding
  165. encPrefix string
  166. encSuffix string
  167. encoded string
  168. utf8 string
  169. }{{
  170. // "A。カ゚ 0208: etc 0212: etc" is a nonsense string that contains ASCII, half-width
  171. // kana, JIS X 0208 (including two near the kink in the Shift JIS second byte
  172. // encoding) and JIS X 0212 encodable codepoints.
  173. //
  174. // "月日は百代の過客にして、行かふ年も又旅人也。" is from the 17th century poem
  175. // "Oku no Hosomichi" and contains both hiragana and kanji.
  176. e: EUCJP,
  177. encoded: "A\x8e\xa1\x8e\xb6\x8e\xdf " +
  178. "0208: \xa1\xa1\xa1\xa2\xa1\xdf\xa1\xe0\xa1\xfd\xa1\xfe\xa2\xa1\xa2\xa2\xf4\xa6 " +
  179. "0212: \x8f\xa2\xaf\x8f\xed\xe3",
  180. utf8: "A。カ゚ " +
  181. "0208: \u3000\u3001\u00d7\u00f7\u25ce\u25c7\u25c6\u25a1\u7199 " +
  182. "0212: \u02d8\u9fa5",
  183. }, {
  184. e: EUCJP,
  185. encoded: "\xb7\xee\xc6\xfc\xa4\xcf\xc9\xb4\xc2\xe5\xa4\xce\xb2\xe1\xb5\xd2" +
  186. "\xa4\xcb\xa4\xb7\xa4\xc6\xa1\xa2\xb9\xd4\xa4\xab\xa4\xd5\xc7\xaf" +
  187. "\xa4\xe2\xcb\xf4\xce\xb9\xbf\xcd\xcc\xe9\xa1\xa3",
  188. utf8: "月日は百代の過客にして、行かふ年も又旅人也。",
  189. }, {
  190. e: ISO2022JP,
  191. encSuffix: "\x1b\x28\x42",
  192. encoded: "\x1b\x28\x49\x21\x36\x5f\x1b\x28\x42 " +
  193. "0208: \x1b\x24\x42\x21\x21\x21\x22\x21\x5f\x21\x60\x21\x7d\x21\x7e\x22\x21\x22\x22\x74\x26",
  194. utf8: "。カ゚ " +
  195. "0208: \u3000\u3001\u00d7\u00f7\u25ce\u25c7\u25c6\u25a1\u7199",
  196. }, {
  197. e: ISO2022JP,
  198. encPrefix: "\x1b\x24\x42",
  199. encSuffix: "\x1b\x28\x42",
  200. encoded: "\x37\x6e\x46\x7c\x24\x4f\x49\x34\x42\x65\x24\x4e\x32\x61\x35\x52" +
  201. "\x24\x4b\x24\x37\x24\x46\x21\x22\x39\x54\x24\x2b\x24\x55\x47\x2f" +
  202. "\x24\x62\x4b\x74\x4e\x39\x3f\x4d\x4c\x69\x21\x23",
  203. utf8: "月日は百代の過客にして、行かふ年も又旅人也。",
  204. }, {
  205. e: ShiftJIS,
  206. encoded: "A\xa1\xb6\xdf " +
  207. "0208: \x81\x40\x81\x41\x81\x7e\x81\x80\x81\x9d\x81\x9e\x81\x9f\x81\xa0\xea\xa4",
  208. utf8: "A。カ゚ " +
  209. "0208: \u3000\u3001\u00d7\u00f7\u25ce\u25c7\u25c6\u25a1\u7199",
  210. }, {
  211. e: ShiftJIS,
  212. encoded: "\x8c\x8e\x93\xfa\x82\xcd\x95\x53\x91\xe3\x82\xcc\x89\xdf\x8b\x71" +
  213. "\x82\xc9\x82\xb5\x82\xc4\x81\x41\x8d\x73\x82\xa9\x82\xd3\x94\x4e" +
  214. "\x82\xe0\x96\x94\x97\xb7\x90\x6c\x96\xe7\x81\x42",
  215. utf8: "月日は百代の過客にして、行かふ年も又旅人也。",
  216. }}
  217. for _, tc := range testCases {
  218. enctest.TestEncoding(t, tc.e, tc.encoded, tc.utf8, tc.encPrefix, tc.encSuffix)
  219. }
  220. }
  221. func TestFiles(t *testing.T) {
  222. enctest.TestFile(t, EUCJP)
  223. enctest.TestFile(t, ISO2022JP)
  224. enctest.TestFile(t, ShiftJIS)
  225. }
  226. func BenchmarkEncoding(b *testing.B) {
  227. enctest.Benchmark(b, EUCJP)
  228. enctest.Benchmark(b, ISO2022JP)
  229. enctest.Benchmark(b, ShiftJIS)
  230. }