transform_test.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. // Copyright 2011 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 norm
  5. import (
  6. "fmt"
  7. "testing"
  8. "golang.org/x/text/transform"
  9. )
  10. func TestTransform(t *testing.T) {
  11. tests := []struct {
  12. f Form
  13. in, out string
  14. eof bool
  15. dstSize int
  16. err error
  17. }{
  18. {NFC, "ab", "ab", true, 2, nil},
  19. {NFC, "qx", "qx", true, 2, nil},
  20. {NFD, "qx", "qx", true, 2, nil},
  21. {NFC, "", "", true, 1, nil},
  22. {NFD, "", "", true, 1, nil},
  23. {NFC, "", "", false, 1, nil},
  24. {NFD, "", "", false, 1, nil},
  25. // Normalized segment does not fit in destination.
  26. {NFD, "ö", "", true, 1, transform.ErrShortDst},
  27. {NFD, "ö", "", true, 2, transform.ErrShortDst},
  28. // As an artifact of the algorithm, only full segments are written.
  29. // This is not strictly required, and some bytes could be written.
  30. // In practice, for Transform to not block, the destination buffer
  31. // should be at least MaxSegmentSize to work anyway and these edge
  32. // conditions will be relatively rare.
  33. {NFC, "ab", "", true, 1, transform.ErrShortDst},
  34. // This is even true for inert runes.
  35. {NFC, "qx", "", true, 1, transform.ErrShortDst},
  36. {NFC, "a\u0300abc", "\u00e0a", true, 4, transform.ErrShortDst},
  37. // We cannot write a segment if successive runes could still change the result.
  38. {NFD, "ö", "", false, 3, transform.ErrShortSrc},
  39. {NFC, "a\u0300", "", false, 4, transform.ErrShortSrc},
  40. {NFD, "a\u0300", "", false, 4, transform.ErrShortSrc},
  41. {NFC, "ö", "", false, 3, transform.ErrShortSrc},
  42. {NFD, "abc", "", false, 1, transform.ErrShortDst},
  43. {NFC, "abc", "", false, 1, transform.ErrShortDst},
  44. {NFC, "abc", "a", false, 2, transform.ErrShortDst},
  45. {NFD, "éfff", "", false, 2, transform.ErrShortDst},
  46. {NFC, "e\u0301fffff", "\u00e9fff", false, 6, transform.ErrShortDst},
  47. {NFD, "ééééé", "e\u0301e\u0301e\u0301", false, 15, transform.ErrShortDst},
  48. {NFC, "a\u0300", "", true, 1, transform.ErrShortDst},
  49. // Theoretically could fit, but won't due to simplified checks.
  50. {NFC, "a\u0300", "", true, 2, transform.ErrShortDst},
  51. {NFC, "a\u0300", "", true, 3, transform.ErrShortDst},
  52. {NFC, "a\u0300", "\u00e0", true, 4, nil},
  53. {NFD, "öa\u0300", "o\u0308", false, 8, transform.ErrShortSrc},
  54. {NFD, "öa\u0300ö", "o\u0308a\u0300", true, 8, transform.ErrShortDst},
  55. {NFD, "öa\u0300ö", "o\u0308a\u0300", false, 12, transform.ErrShortSrc},
  56. // Illegal input is copied verbatim.
  57. {NFD, "\xbd\xb2=\xbc ", "\xbd\xb2=\xbc ", true, 8, nil},
  58. }
  59. b := make([]byte, 100)
  60. for i, tt := range tests {
  61. t.Run(fmt.Sprintf("%d:%s", i, tt.in), func(t *testing.T) {
  62. nDst, _, err := tt.f.Transform(b[:tt.dstSize], []byte(tt.in), tt.eof)
  63. out := string(b[:nDst])
  64. if out != tt.out || err != tt.err {
  65. t.Errorf("was %+q (%v); want %+q (%v)", out, err, tt.out, tt.err)
  66. }
  67. if want := tt.f.String(tt.in)[:nDst]; want != out {
  68. t.Errorf("incorrect normalization: was %+q; want %+q", out, want)
  69. }
  70. })
  71. }
  72. }
  73. var transBufSizes = []int{
  74. MaxTransformChunkSize,
  75. 3 * MaxTransformChunkSize / 2,
  76. 2 * MaxTransformChunkSize,
  77. 3 * MaxTransformChunkSize,
  78. 100 * MaxTransformChunkSize,
  79. }
  80. func doTransNorm(f Form, buf []byte, b []byte) []byte {
  81. acc := []byte{}
  82. for p := 0; p < len(b); {
  83. nd, ns, _ := f.Transform(buf[:], b[p:], true)
  84. p += ns
  85. acc = append(acc, buf[:nd]...)
  86. }
  87. return acc
  88. }
  89. func TestTransformNorm(t *testing.T) {
  90. for _, sz := range transBufSizes {
  91. buf := make([]byte, sz)
  92. runNormTests(t, fmt.Sprintf("Transform:%d", sz), func(f Form, out []byte, s string) []byte {
  93. return doTransNorm(f, buf, append(out, s...))
  94. })
  95. }
  96. }