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.
14 "golang.org/x/text/language"
17 func TestGetIntApprox(t *testing.T) {
18 const big = 1234567890
19 testCases := []struct {
27 {"123", 0, 2, 1, big},
30 {"12345", 3, 4, 2, 4},
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},
41 // Translation of examples in MatchDigits.
43 {"123", 0, 3, 3, 123}, // 123
44 {"1234", 0, 3, 3, 123}, // 123.4
45 {"1", 0, 6, 8, 100000}, // 100000
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
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)
57 t.Errorf("got %d; want %d", got, tc.want)
63 func mkDigits(s string) []byte {
71 func TestValidForms(t *testing.T) {
72 testCases := []struct {
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}},
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)
90 func TestOrdinal(t *testing.T) {
91 testPlurals(t, Ordinal, ordinalTests)
94 func TestCardinal(t *testing.T) {
95 testPlurals(t, Cardinal, cardinalTests)
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)
103 for _, s := range tc.integer {
104 a := strings.Split(s, "~")
105 from := parseUint(t, a[0])
108 to = parseUint(t, a[1])
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))
115 digits := []byte(fmt.Sprint(n))
116 for i := range digits {
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))
126 for _, s := range tc.decimal {
127 a := strings.Split(s, "~")
128 from, scale := parseFixedPoint(t, a[0])
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)
137 for i := 0; i < scale; i++ {
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) {
147 for tt > 0 && tt%10 == 0 {
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))
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))
157 exp := strings.IndexByte(num, '.')
158 digits := []byte(strings.Replace(num, ".", "", 1))
159 for i := range digits {
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))
172 func parseUint(t *testing.T, s string) int {
173 val, err := strconv.ParseUint(s, 10, 32)
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)
187 return int(v), len(s) - p
190 func BenchmarkPluralSimpleCases(b *testing.B) {
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
204 func BenchmarkPluralComplexCases(b *testing.B) {
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