pinyin_test.go 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. package pinyin
  2. import (
  3. "reflect"
  4. "testing"
  5. )
  6. type pinyinFunc func(string, Args) [][]string
  7. type testCase struct {
  8. args Args
  9. result [][]string
  10. }
  11. func testPinyin(t *testing.T, s string, d []testCase, f pinyinFunc) {
  12. for _, tc := range d {
  13. v := f(s, tc.args)
  14. if !reflect.DeepEqual(v, tc.result) {
  15. t.Errorf("Expected %s, got %s", tc.result, v)
  16. }
  17. }
  18. }
  19. func TestPinyin(t *testing.T) {
  20. hans := "中国人"
  21. testData := []testCase{
  22. // default
  23. {
  24. Args{Style: Normal},
  25. [][]string{
  26. {"zhong"},
  27. {"guo"},
  28. {"ren"},
  29. },
  30. },
  31. // default
  32. {
  33. NewArgs(),
  34. [][]string{
  35. {"zhong"},
  36. {"guo"},
  37. {"ren"},
  38. },
  39. },
  40. // Normal
  41. {
  42. Args{Style: Normal},
  43. [][]string{
  44. {"zhong"},
  45. {"guo"},
  46. {"ren"},
  47. },
  48. },
  49. // Tone
  50. {
  51. Args{Style: Tone},
  52. [][]string{
  53. {"zhōng"},
  54. {"guó"},
  55. {"rén"},
  56. },
  57. },
  58. // Tone2
  59. {
  60. Args{Style: Tone2},
  61. [][]string{
  62. {"zho1ng"},
  63. {"guo2"},
  64. {"re2n"},
  65. },
  66. },
  67. // Tone3
  68. {
  69. Args{Style: Tone3},
  70. [][]string{
  71. {"zhong1"},
  72. {"guo2"},
  73. {"ren2"},
  74. },
  75. },
  76. // Initials
  77. {
  78. Args{Style: Initials},
  79. [][]string{
  80. {"zh"},
  81. {"g"},
  82. {"r"},
  83. },
  84. },
  85. // FirstLetter
  86. {
  87. Args{Style: FirstLetter},
  88. [][]string{
  89. {"z"},
  90. {"g"},
  91. {"r"},
  92. },
  93. },
  94. // Finals
  95. {
  96. Args{Style: Finals},
  97. [][]string{
  98. {"ong"},
  99. {"uo"},
  100. {"en"},
  101. },
  102. },
  103. // FinalsTone
  104. {
  105. Args{Style: FinalsTone},
  106. [][]string{
  107. {"ōng"},
  108. {"uó"},
  109. {"én"},
  110. },
  111. },
  112. // FinalsTone2
  113. {
  114. Args{Style: FinalsTone2},
  115. [][]string{
  116. {"o1ng"},
  117. {"uo2"},
  118. {"e2n"},
  119. },
  120. },
  121. // FinalsTone3
  122. {
  123. Args{Style: FinalsTone3},
  124. [][]string{
  125. {"ong1"},
  126. {"uo2"},
  127. {"en2"},
  128. },
  129. },
  130. // Heteronym
  131. {
  132. Args{Heteronym: true},
  133. [][]string{
  134. {"zhong", "zhong"},
  135. {"guo"},
  136. {"ren"},
  137. },
  138. },
  139. }
  140. testPinyin(t, hans, testData, Pinyin)
  141. // 测试不是多音字的 Heteronym
  142. hans = "你"
  143. testData = []testCase{
  144. {
  145. Args{},
  146. [][]string{
  147. {"ni"},
  148. },
  149. },
  150. {
  151. Args{Heteronym: true},
  152. [][]string{
  153. {"ni"},
  154. },
  155. },
  156. }
  157. testPinyin(t, hans, testData, Pinyin)
  158. }
  159. func TestNoneHans(t *testing.T) {
  160. s := "abc"
  161. v := Pinyin(s, NewArgs())
  162. value := [][]string{}
  163. if !reflect.DeepEqual(v, value) {
  164. t.Errorf("Expected %s, got %s", value, v)
  165. }
  166. }
  167. func TestLazyPinyin(t *testing.T) {
  168. s := "中国人"
  169. v := LazyPinyin(s, Args{})
  170. value := []string{"zhong", "guo", "ren"}
  171. if !reflect.DeepEqual(v, value) {
  172. t.Errorf("Expected %s, got %s", value, v)
  173. }
  174. s = "中国人abc"
  175. v = LazyPinyin(s, Args{})
  176. value = []string{"zhong", "guo", "ren"}
  177. if !reflect.DeepEqual(v, value) {
  178. t.Errorf("Expected %s, got %s", value, v)
  179. }
  180. }
  181. func TestSlug(t *testing.T) {
  182. s := "中国人"
  183. v := Slug(s, Args{})
  184. value := "zhongguoren"
  185. if v != value {
  186. t.Errorf("Expected %s, got %s", value, v)
  187. }
  188. v = Slug(s, Args{Separator: ","})
  189. value = "zhong,guo,ren"
  190. if v != value {
  191. t.Errorf("Expected %s, got %s", value, v)
  192. }
  193. a := NewArgs()
  194. v = Slug(s, a)
  195. value = "zhong-guo-ren"
  196. if v != value {
  197. t.Errorf("Expected %s, got %s", value, v)
  198. }
  199. s = "中国人abc,,中"
  200. v = Slug(s, a)
  201. value = "zhong-guo-ren-zhong"
  202. if v != value {
  203. t.Errorf("Expected %s, got %s", value, v)
  204. }
  205. }
  206. func TestFinal(t *testing.T) {
  207. value := "an"
  208. v := final("an")
  209. if v != value {
  210. t.Errorf("Expected %s, got %s", value, v)
  211. }
  212. }
  213. func TestFallback(t *testing.T) {
  214. hans := "中国人abc"
  215. testData := []testCase{
  216. // default
  217. {
  218. NewArgs(),
  219. [][]string{
  220. {"zhong"},
  221. {"guo"},
  222. {"ren"},
  223. },
  224. },
  225. // custom
  226. {
  227. Args{
  228. Fallback: func(r rune, a Args) []string {
  229. return []string{"la"}
  230. },
  231. },
  232. [][]string{
  233. {"zhong"},
  234. {"guo"},
  235. {"ren"},
  236. {"la"},
  237. {"la"},
  238. {"la"},
  239. },
  240. },
  241. // custom
  242. {
  243. Args{
  244. Heteronym: true,
  245. Fallback: func(r rune, a Args) []string {
  246. return []string{"la", "wo"}
  247. },
  248. },
  249. [][]string{
  250. {"zhong", "zhong"},
  251. {"guo"},
  252. {"ren"},
  253. {"la", "wo"},
  254. {"la", "wo"},
  255. {"la", "wo"},
  256. },
  257. },
  258. }
  259. testPinyin(t, hans, testData, Pinyin)
  260. }
  261. type testItem struct {
  262. hans string
  263. args Args
  264. result [][]string
  265. }
  266. func testPinyinUpdate(t *testing.T, d []testItem, f pinyinFunc) {
  267. for _, tc := range d {
  268. v := f(tc.hans, tc.args)
  269. if !reflect.DeepEqual(v, tc.result) {
  270. t.Errorf("Expected %s, got %s", tc.result, v)
  271. }
  272. }
  273. }
  274. func TestUpdated(t *testing.T) {
  275. testData := []testItem{
  276. // 误把 yu 放到声母列表了
  277. {"鱼", Args{Style: Tone2}, [][]string{{"yu2"}}},
  278. {"鱼", Args{Style: Tone3}, [][]string{{"yu2"}}},
  279. {"鱼", Args{Style: Finals}, [][]string{{"v"}}},
  280. {"雨", Args{Style: Tone2}, [][]string{{"yu3"}}},
  281. {"雨", Args{Style: Tone3}, [][]string{{"yu3"}}},
  282. {"雨", Args{Style: Finals}, [][]string{{"v"}}},
  283. {"元", Args{Style: Tone2}, [][]string{{"yua2n"}}},
  284. {"元", Args{Style: Tone3}, [][]string{{"yuan2"}}},
  285. {"元", Args{Style: Finals}, [][]string{{"van"}}},
  286. // y, w 也不是拼音, yu的韵母是v, yi的韵母是i, wu的韵母是u
  287. {"呀", Args{Style: Initials}, [][]string{{""}}},
  288. {"呀", Args{Style: Tone2}, [][]string{{"ya"}}},
  289. {"呀", Args{Style: Tone3}, [][]string{{"ya"}}},
  290. {"呀", Args{Style: Finals}, [][]string{{"ia"}}},
  291. {"无", Args{Style: Initials}, [][]string{{""}}},
  292. {"无", Args{Style: Tone2}, [][]string{{"wu2"}}},
  293. {"无", Args{Style: Tone3}, [][]string{{"wu2"}}},
  294. {"无", Args{Style: Finals}, [][]string{{"u"}}},
  295. {"衣", Args{Style: Tone2}, [][]string{{"yi1"}}},
  296. {"衣", Args{Style: Tone3}, [][]string{{"yi1"}}},
  297. {"衣", Args{Style: Finals}, [][]string{{"i"}}},
  298. {"万", Args{Style: Tone2}, [][]string{{"wa4n"}}},
  299. {"万", Args{Style: Tone3}, [][]string{{"wan4"}}},
  300. {"万", Args{Style: Finals}, [][]string{{"uan"}}},
  301. // ju, qu, xu 的韵母应该是 v
  302. {"具", Args{Style: FinalsTone}, [][]string{{"ǜ"}}},
  303. {"具", Args{Style: FinalsTone2}, [][]string{{"v4"}}},
  304. {"具", Args{Style: FinalsTone3}, [][]string{{"v4"}}},
  305. {"具", Args{Style: Finals}, [][]string{{"v"}}},
  306. {"取", Args{Style: FinalsTone}, [][]string{{"ǚ"}}},
  307. {"取", Args{Style: FinalsTone2}, [][]string{{"v3"}}},
  308. {"取", Args{Style: FinalsTone3}, [][]string{{"v3"}}},
  309. {"取", Args{Style: Finals}, [][]string{{"v"}}},
  310. {"徐", Args{Style: FinalsTone}, [][]string{{"ǘ"}}},
  311. {"徐", Args{Style: FinalsTone2}, [][]string{{"v2"}}},
  312. {"徐", Args{Style: FinalsTone3}, [][]string{{"v2"}}},
  313. {"徐", Args{Style: Finals}, [][]string{{"v"}}},
  314. // # ń
  315. {"嗯", Args{Style: Normal}, [][]string{{"n"}}},
  316. {"嗯", Args{Style: Tone}, [][]string{{"ń"}}},
  317. {"嗯", Args{Style: Tone2}, [][]string{{"n2"}}},
  318. {"嗯", Args{Style: Tone3}, [][]string{{"n2"}}},
  319. {"嗯", Args{Style: Initials}, [][]string{{""}}},
  320. {"嗯", Args{Style: FirstLetter}, [][]string{{"n"}}},
  321. {"嗯", Args{Style: Finals}, [][]string{{"n"}}},
  322. {"嗯", Args{Style: FinalsTone}, [][]string{{"ń"}}},
  323. {"嗯", Args{Style: FinalsTone2}, [][]string{{"n2"}}},
  324. {"嗯", Args{Style: FinalsTone3}, [][]string{{"n2"}}},
  325. // # ḿ \u1e3f U+1E3F
  326. {"呣", Args{Style: Normal}, [][]string{{"m"}}},
  327. {"呣", Args{Style: Tone}, [][]string{{"ḿ"}}},
  328. {"呣", Args{Style: Tone2}, [][]string{{"m2"}}},
  329. {"呣", Args{Style: Tone3}, [][]string{{"m2"}}},
  330. {"呣", Args{Style: Initials}, [][]string{{""}}},
  331. {"呣", Args{Style: FirstLetter}, [][]string{{"m"}}},
  332. {"呣", Args{Style: Finals}, [][]string{{"m"}}},
  333. {"呣", Args{Style: FinalsTone}, [][]string{{"ḿ"}}},
  334. {"呣", Args{Style: FinalsTone2}, [][]string{{"m2"}}},
  335. {"呣", Args{Style: FinalsTone3}, [][]string{{"m2"}}},
  336. // 去除 0
  337. {"啊", Args{Style: Tone2}, [][]string{{"a"}}},
  338. {"啊", Args{Style: Tone3}, [][]string{{"a"}}},
  339. {"侵略", Args{Style: Tone2}, [][]string{{"qi1n"}, {"lve4"}}},
  340. {"侵略", Args{Style: FinalsTone2}, [][]string{{"i1n"}, {"ve4"}}},
  341. {"侵略", Args{Style: FinalsTone3}, [][]string{{"in1"}, {"ve4"}}},
  342. }
  343. testPinyinUpdate(t, testData, Pinyin)
  344. }
  345. func TestConvert(t *testing.T) {
  346. s := "中国人"
  347. v := Convert(s, nil)
  348. value := [][]string{{"zhong"}, {"guo"}, {"ren"}}
  349. if !reflect.DeepEqual(v, value) {
  350. t.Errorf("Expected %s, got %s", value, v)
  351. }
  352. a := NewArgs()
  353. v = Convert(s, &a)
  354. if !reflect.DeepEqual(v, value) {
  355. t.Errorf("Expected %s, got %s", value, v)
  356. }
  357. }
  358. func TestLazyConvert(t *testing.T) {
  359. s := "中国人"
  360. v := LazyConvert(s, nil)
  361. value := []string{"zhong", "guo", "ren"}
  362. if !reflect.DeepEqual(v, value) {
  363. t.Errorf("Expected %s, got %s", value, v)
  364. }
  365. a := NewArgs()
  366. v = LazyConvert(s, &a)
  367. if !reflect.DeepEqual(v, value) {
  368. t.Errorf("Expected %s, got %s", value, v)
  369. }
  370. }
  371. func TestPinyin_fallback_issue_35(t *testing.T) {
  372. a := NewArgs()
  373. a.Separator = ""
  374. a.Style = FirstLetter
  375. a.Fallback = func(r rune, a Args) []string {
  376. return []string{string(r)}
  377. }
  378. var s = "重。,a庆"
  379. v := Pinyin(s, a)
  380. expect := [][]string{{"z"}, {"。"}, {","}, {"a"}, {"q"}}
  381. if !reflect.DeepEqual(v, expect) {
  382. t.Errorf("Expected %s, got %s", expect, v)
  383. }
  384. }