1 // Copyright 2017 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.
12 "golang.org/x/text/internal/catmsg"
13 "golang.org/x/text/language"
14 "golang.org/x/text/message/catalog"
17 func TestSelect(t *testing.T) {
18 lang := language.English
24 testCases := []struct {
31 msg: Selectf(1, "%d", "one", "foo", "other", "bar"),
33 {arg: 0, result: "bar"},
34 {arg: 1, result: "foo"},
35 {arg: 2, result: "bar"},
36 {arg: opposite(1), result: "bar"},
37 {arg: opposite(2), result: "foo"},
38 {arg: "unknown", result: "bar"}, // other
45 "one", "cannot match", // never matches
46 "<5", "<5", // never matches
50 {arg: 0, result: "zero"},
51 {arg: 1, result: "one"},
52 {arg: 2, result: "<5"},
53 {arg: 4, result: "<5"},
54 {arg: 5, result: "=5"},
55 {arg: 6, result: "other"},
56 {arg: "unknown", result: "other"},
60 msg: Selectf(1, "%.2f", "one", "foo", "other", "bar"),
62 // fractions are always plural in english
63 {arg: 0, result: "bar"},
64 {arg: 1, result: "bar"},
67 desc: "decimal without fractions",
68 msg: Selectf(1, "%.of", "one", "foo", "other", "bar"),
70 // fractions are always plural in english
71 {arg: 0, result: "bar"},
72 {arg: 1, result: "foo"},
76 msg: Selectf(1, "%.0e", "one", "foo", "other", "bar"),
78 {arg: 0, result: "bar"},
79 {arg: 1, result: "foo"},
83 msg: Selectf(1, "%.1g", "one", "foo", "other", "bar"),
85 // fractions are always plural in english
86 {arg: 0, result: "bar"},
87 {arg: 1, result: "foo"},
88 {arg: 2, result: "bar"},
92 msg: Selectf(1, "", "one", "foo", "other", "bar"),
94 {arg: 0, result: "bar"},
95 {arg: 1, result: "foo"},
96 {arg: 2, result: "bar"},
97 {arg: 1.0, result: "bar"},
101 msg: Selectf(1, "", "other", Selectf(2, "", "one", "foo", "other", "bar")),
103 {arg: 0, result: "bar"},
104 {arg: 1, result: "foo"},
105 {arg: 2, result: "bar"},
108 desc: "arg unavailable",
109 msg: Selectf(100, "%.2f", "one", "foo", "other", "bar"),
110 tests: []test{{arg: 1, result: "bar"}},
113 msg: Selectf(1, "%.2f", "one", "foo"),
114 tests: []test{{arg: 0, result: "bar", err: catmsg.ErrNoMatch.Error()}},
116 desc: "error invalid form",
117 err: `invalid plural form "excessive"`,
118 msg: Selectf(1, "%d", "excessive", "foo"),
120 desc: "error form not used by language",
121 err: `form "many" not supported for language "en"`,
122 msg: Selectf(1, "%d", "many", "foo"),
124 desc: "error invalid selector",
125 err: `selector of type int; want string or Form`,
126 msg: Selectf(1, "%d", 1, "foo"),
128 desc: "error missing message",
129 err: `no message defined for selector one`,
130 msg: Selectf(1, "%d", "one"),
132 desc: "error invalid number",
133 err: `invalid number in selector "<1.00"`,
134 msg: Selectf(1, "%d", "<1.00"),
136 desc: "error empty selector",
137 err: `empty selector`,
138 msg: Selectf(1, "%d", "", "foo"),
140 desc: "error invalid message",
141 err: `message of type int; must be string or catalog.Message`,
142 msg: Selectf(1, "%d", "one", 3),
144 desc: "nested error",
145 err: `empty selector`,
146 msg: Selectf(1, "", "other", Selectf(2, "", "")),
148 for _, tc := range testCases {
149 t.Run(tc.desc, func(t *testing.T) {
150 data, err := catmsg.Compile(lang, nil, tc.msg)
151 chkError(t, err, tc.err)
152 for _, tx := range tc.tests {
153 t.Run(fmt.Sprint(tx.arg), func(t *testing.T) {
154 r := renderer{arg: tx.arg}
155 d := catmsg.NewDecoder(lang, &r, nil)
156 err := d.Execute(data)
157 chkError(t, err, tx.err)
158 if r.result != tx.result {
159 t.Errorf("got %q; want %q", r.result, tx.result)
167 func chkError(t *testing.T, got error, want string) {
168 if (got == nil && want != "") ||
169 (got != nil && (want == "" || !strings.Contains(got.Error(), want))) {
170 t.Fatalf("got %v; want %v", got, want)
177 type renderer struct {
182 func (r *renderer) Render(s string) { r.result += s }
183 func (r *renderer) Arg(i int) interface{} {
184 if i > 10 { // Allow testing "arg unavailable" path
192 func (o opposite) PluralForm(lang language.Tag, scale int) (Form, int) {