bidirule_test.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. // Copyright 2016 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 bidirule
  5. import (
  6. "fmt"
  7. "testing"
  8. "golang.org/x/text/internal/testtext"
  9. "golang.org/x/text/unicode/bidi"
  10. )
  11. const (
  12. strL = "ABC" // Left to right - most letters in LTR scripts
  13. strR = "עברית" // Right to left - most letters in non-Arabic RTL scripts
  14. strAL = "دبي" // Arabic letters - most letters in the Arabic script
  15. strEN = "123" // European Number (0-9, and Extended Arabic-Indic numbers)
  16. strES = "+-" // European Number Separator (+ and -)
  17. strET = "$" // European Number Terminator (currency symbols, the hash sign, the percent sign and so on)
  18. strAN = "\u0660" // Arabic Number; this encompasses the Arabic-Indic numbers, but not the Extended Arabic-Indic numbers
  19. strCS = "," // Common Number Separator (. , / : et al)
  20. strNSM = "\u0300" // Nonspacing Mark - most combining accents
  21. strBN = "\u200d" // Boundary Neutral - control characters (ZWNJ, ZWJ, and others)
  22. strB = "\u2029" // Paragraph Separator
  23. strS = "\u0009" // Segment Separator
  24. strWS = " " // Whitespace, including the SPACE character
  25. strON = "@" // Other Neutrals, including @, &, parentheses, MIDDLE DOT
  26. )
  27. type ruleTest struct {
  28. in string
  29. dir bidi.Direction
  30. n int // position at which the rule fails
  31. err error
  32. // For tests that split the string in two.
  33. pSrc int // number of source bytes to consume first
  34. szDst int // size of destination buffer
  35. nSrc int // source bytes consumed and bytes written
  36. err0 error // error after first run
  37. }
  38. func init() {
  39. for rule, cases := range testCases {
  40. for i, tc := range cases {
  41. if tc.err == nil {
  42. testCases[rule][i].n = len(tc.in)
  43. }
  44. }
  45. }
  46. }
  47. func doTests(t *testing.T, fn func(t *testing.T, tc ruleTest)) {
  48. for rule, cases := range testCases {
  49. for i, tc := range cases {
  50. name := fmt.Sprintf("%d/%d:%+q:%s", rule, i, tc.in, tc.in)
  51. testtext.Run(t, name, func(t *testing.T) {
  52. fn(t, tc)
  53. })
  54. }
  55. }
  56. }
  57. func TestDirection(t *testing.T) {
  58. doTests(t, func(t *testing.T, tc ruleTest) {
  59. dir := Direction([]byte(tc.in))
  60. if dir != tc.dir {
  61. t.Errorf("dir was %v; want %v", dir, tc.dir)
  62. }
  63. })
  64. }
  65. func TestDirectionString(t *testing.T) {
  66. doTests(t, func(t *testing.T, tc ruleTest) {
  67. dir := DirectionString(tc.in)
  68. if dir != tc.dir {
  69. t.Errorf("dir was %v; want %v", dir, tc.dir)
  70. }
  71. })
  72. }
  73. func TestValid(t *testing.T) {
  74. doTests(t, func(t *testing.T, tc ruleTest) {
  75. got := Valid([]byte(tc.in))
  76. want := tc.err == nil
  77. if got != want {
  78. t.Fatalf("Valid: got %v; want %v", got, want)
  79. }
  80. got = ValidString(tc.in)
  81. want = tc.err == nil
  82. if got != want {
  83. t.Fatalf("Valid: got %v; want %v", got, want)
  84. }
  85. })
  86. }
  87. func TestSpan(t *testing.T) {
  88. doTests(t, func(t *testing.T, tc ruleTest) {
  89. // Skip tests that test for limited destination buffer size.
  90. if tc.szDst > 0 {
  91. return
  92. }
  93. r := New()
  94. src := []byte(tc.in)
  95. n, err := r.Span(src[:tc.pSrc], tc.pSrc == len(tc.in))
  96. if err != tc.err0 {
  97. t.Errorf("err0 was %v; want %v", err, tc.err0)
  98. }
  99. if n != tc.nSrc {
  100. t.Fatalf("nSrc was %d; want %d", n, tc.nSrc)
  101. }
  102. n, err = r.Span(src[n:], true)
  103. if err != tc.err {
  104. t.Errorf("error was %v; want %v", err, tc.err)
  105. }
  106. if got := n + tc.nSrc; got != tc.n {
  107. t.Errorf("n was %d; want %d", got, tc.n)
  108. }
  109. })
  110. }
  111. func TestTransform(t *testing.T) {
  112. doTests(t, func(t *testing.T, tc ruleTest) {
  113. r := New()
  114. src := []byte(tc.in)
  115. dst := make([]byte, len(tc.in))
  116. if tc.szDst > 0 {
  117. dst = make([]byte, tc.szDst)
  118. }
  119. // First transform operates on a zero-length string for most tests.
  120. nDst, nSrc, err := r.Transform(dst, src[:tc.pSrc], tc.pSrc == len(tc.in))
  121. if err != tc.err0 {
  122. t.Errorf("err0 was %v; want %v", err, tc.err0)
  123. }
  124. if nDst != nSrc {
  125. t.Fatalf("nDst (%d) and nSrc (%d) should match", nDst, nSrc)
  126. }
  127. if nSrc != tc.nSrc {
  128. t.Fatalf("nSrc was %d; want %d", nSrc, tc.nSrc)
  129. }
  130. dst1 := make([]byte, len(tc.in))
  131. copy(dst1, dst[:nDst])
  132. nDst, nSrc, err = r.Transform(dst1[nDst:], src[nSrc:], true)
  133. if err != tc.err {
  134. t.Errorf("error was %v; want %v", err, tc.err)
  135. }
  136. if nDst != nSrc {
  137. t.Fatalf("nDst (%d) and nSrc (%d) should match", nDst, nSrc)
  138. }
  139. n := nSrc + tc.nSrc
  140. if n != tc.n {
  141. t.Fatalf("n was %d; want %d", n, tc.n)
  142. }
  143. if got, want := string(dst1[:n]), tc.in[:tc.n]; got != want {
  144. t.Errorf("got %+q; want %+q", got, want)
  145. }
  146. })
  147. }