OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / text / feature / plural / plural_test.go
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
5 package plural
6
7 import (
8         "fmt"
9         "reflect"
10         "strconv"
11         "strings"
12         "testing"
13
14         "golang.org/x/text/language"
15 )
16
17 func TestGetIntApprox(t *testing.T) {
18         const big = 1234567890
19         testCases := []struct {
20                 digits string
21                 start  int
22                 end    int
23                 nMod   int
24                 want   int
25         }{
26                 {"123", 0, 1, 1, 1},
27                 {"123", 0, 2, 1, big},
28                 {"123", 0, 2, 2, 12},
29                 {"123", 3, 4, 2, 0},
30                 {"12345", 3, 4, 2, 4},
31                 {"40", 0, 1, 2, 4},
32                 {"1", 0, 7, 2, big},
33
34                 {"123", 0, 5, 2, big},
35                 {"123", 0, 5, 3, big},
36                 {"123", 0, 5, 4, big},
37                 {"123", 0, 5, 5, 12300},
38                 {"123", 0, 5, 6, 12300},
39                 {"123", 0, 5, 7, 12300},
40
41                 // Translation of examples in MatchDigits.
42                 // Integer parts
43                 {"123", 0, 3, 3, 123},  // 123
44                 {"1234", 0, 3, 3, 123}, // 123.4
45                 {"1", 0, 6, 8, 100000}, // 100000
46
47                 // Fraction parts
48                 {"123", 3, 3, 3, 0},   // 123
49                 {"1234", 3, 4, 3, 4},  // 123.4
50                 {"1234", 3, 5, 3, 40}, // 123.40
51                 {"1", 6, 8, 8, 0},     // 100000.00
52         }
53         for _, tc := range testCases {
54                 t.Run(fmt.Sprintf("%s:%d:%d/%d", tc.digits, tc.start, tc.end, tc.nMod), func(t *testing.T) {
55                         got := getIntApprox(mkDigits(tc.digits), tc.start, tc.end, tc.nMod, big)
56                         if got != tc.want {
57                                 t.Errorf("got %d; want %d", got, tc.want)
58                         }
59                 })
60         }
61 }
62
63 func mkDigits(s string) []byte {
64         b := []byte(s)
65         for i := range b {
66                 b[i] -= '0'
67         }
68         return b
69 }
70
71 func TestValidForms(t *testing.T) {
72         testCases := []struct {
73                 tag  language.Tag
74                 want []Form
75         }{
76                 {language.AmericanEnglish, []Form{Other, One}},
77                 {language.Portuguese, []Form{Other, One}},
78                 {language.Latvian, []Form{Other, Zero, One}},
79                 {language.Arabic, []Form{Other, Zero, One, Two, Few, Many}},
80                 {language.Russian, []Form{Other, One, Few, Many}},
81         }
82         for _, tc := range testCases {
83                 got := validForms(cardinal, tc.tag)
84                 if !reflect.DeepEqual(got, tc.want) {
85                         t.Errorf("validForms(%v): got %v; want %v", tc.tag, got, tc.want)
86                 }
87         }
88 }
89
90 func TestOrdinal(t *testing.T) {
91         testPlurals(t, Ordinal, ordinalTests)
92 }
93
94 func TestCardinal(t *testing.T) {
95         testPlurals(t, Cardinal, cardinalTests)
96 }
97
98 func testPlurals(t *testing.T, p *Rules, testCases []pluralTest) {
99         for _, tc := range testCases {
100                 for _, loc := range strings.Split(tc.locales, " ") {
101                         tag := language.MustParse(loc)
102                         // Test integers
103                         for _, s := range tc.integer {
104                                 a := strings.Split(s, "~")
105                                 from := parseUint(t, a[0])
106                                 to := from
107                                 if len(a) > 1 {
108                                         to = parseUint(t, a[1])
109                                 }
110                                 for n := from; n <= to; n++ {
111                                         t.Run(fmt.Sprintf("%s/int(%d)", loc, n), func(t *testing.T) {
112                                                 if f := p.matchComponents(tag, n, 0, 0); f != Form(tc.form) {
113                                                         t.Errorf("matchComponents: got %v; want %v", f, Form(tc.form))
114                                                 }
115                                                 digits := []byte(fmt.Sprint(n))
116                                                 for i := range digits {
117                                                         digits[i] -= '0'
118                                                 }
119                                                 if f := p.MatchDigits(tag, digits, len(digits), 0); f != Form(tc.form) {
120                                                         t.Errorf("MatchDigits: got %v; want %v", f, Form(tc.form))
121                                                 }
122                                         })
123                                 }
124                         }
125                         // Test decimals
126                         for _, s := range tc.decimal {
127                                 a := strings.Split(s, "~")
128                                 from, scale := parseFixedPoint(t, a[0])
129                                 to := from
130                                 if len(a) > 1 {
131                                         var toScale int
132                                         if to, toScale = parseFixedPoint(t, a[1]); toScale != scale {
133                                                 t.Fatalf("%s:%s: non-matching scales %d versus %d", loc, s, scale, toScale)
134                                         }
135                                 }
136                                 m := 1
137                                 for i := 0; i < scale; i++ {
138                                         m *= 10
139                                 }
140                                 for n := from; n <= to; n++ {
141                                         num := fmt.Sprintf("%[1]d.%0[3]*[2]d", n/m, n%m, scale)
142                                         name := fmt.Sprintf("%s:dec(%s)", loc, num)
143                                         t.Run(name, func(t *testing.T) {
144                                                 ff := n % m
145                                                 tt := ff
146                                                 w := scale
147                                                 for tt > 0 && tt%10 == 0 {
148                                                         w--
149                                                         tt /= 10
150                                                 }
151                                                 if f := p.MatchPlural(tag, n/m, scale, w, ff, tt); f != Form(tc.form) {
152                                                         t.Errorf("MatchPlural: got %v; want %v", f, Form(tc.form))
153                                                 }
154                                                 if f := p.matchComponents(tag, n/m, n%m, scale); f != Form(tc.form) {
155                                                         t.Errorf("matchComponents: got %v; want %v", f, Form(tc.form))
156                                                 }
157                                                 exp := strings.IndexByte(num, '.')
158                                                 digits := []byte(strings.Replace(num, ".", "", 1))
159                                                 for i := range digits {
160                                                         digits[i] -= '0'
161                                                 }
162                                                 if f := p.MatchDigits(tag, digits, exp, scale); f != Form(tc.form) {
163                                                         t.Errorf("MatchDigits: got %v; want %v", f, Form(tc.form))
164                                                 }
165                                         })
166                                 }
167                         }
168                 }
169         }
170 }
171
172 func parseUint(t *testing.T, s string) int {
173         val, err := strconv.ParseUint(s, 10, 32)
174         if err != nil {
175                 t.Fatal(err)
176         }
177         return int(val)
178 }
179
180 func parseFixedPoint(t *testing.T, s string) (val, scale int) {
181         p := strings.Index(s, ".")
182         s = strings.Replace(s, ".", "", 1)
183         v, err := strconv.ParseUint(s, 10, 32)
184         if err != nil {
185                 t.Fatal(err)
186         }
187         return int(v), len(s) - p
188 }
189
190 func BenchmarkPluralSimpleCases(b *testing.B) {
191         p := Cardinal
192         en, _ := language.CompactIndex(language.English)
193         zh, _ := language.CompactIndex(language.Chinese)
194         for i := 0; i < b.N; i++ {
195                 matchPlural(p, en, 0, 0, 0)  // 0
196                 matchPlural(p, en, 1, 0, 0)  // 1
197                 matchPlural(p, en, 2, 12, 3) // 2.120
198                 matchPlural(p, zh, 0, 0, 0)  // 0
199                 matchPlural(p, zh, 1, 0, 0)  // 1
200                 matchPlural(p, zh, 2, 12, 3) // 2.120
201         }
202 }
203
204 func BenchmarkPluralComplexCases(b *testing.B) {
205         p := Cardinal
206         ar, _ := language.CompactIndex(language.Arabic)
207         lv, _ := language.CompactIndex(language.Latvian)
208         for i := 0; i < b.N; i++ {
209                 matchPlural(p, lv, 0, 19, 2)    // 0.19
210                 matchPlural(p, lv, 11, 0, 3)    // 11.000
211                 matchPlural(p, lv, 100, 123, 4) // 0.1230
212                 matchPlural(p, ar, 0, 0, 0)     // 0
213                 matchPlural(p, ar, 110, 0, 0)   // 110
214                 matchPlural(p, ar, 99, 99, 2)   // 99.99
215         }
216 }