...

Source file src/golang.org/x/text/feature/plural/message_test.go

Documentation: golang.org/x/text/feature/plural

     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.
     4  
     5  package plural
     6  
     7  import (
     8  	"fmt"
     9  	"strings"
    10  	"testing"
    11  
    12  	"golang.org/x/text/internal/catmsg"
    13  	"golang.org/x/text/language"
    14  	"golang.org/x/text/message/catalog"
    15  )
    16  
    17  func TestSelect(t *testing.T) {
    18  	lang := language.English
    19  	type test struct {
    20  		arg    interface{}
    21  		result string
    22  		err    string
    23  	}
    24  	testCases := []struct {
    25  		desc  string
    26  		msg   catalog.Message
    27  		err   string
    28  		tests []test
    29  	}{{
    30  		desc: "basic",
    31  		msg:  Selectf(1, "%d", "one", "foo", "other", "bar"),
    32  		tests: []test{
    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
    39  		},
    40  	}, {
    41  		desc: "comparisons",
    42  		msg: Selectf(1, "%d",
    43  			"=0", "zero",
    44  			"=1", "one",
    45  			"one", "cannot match", // never matches
    46  			"<5", "<5", // never matches
    47  			"=5", "=5",
    48  			Other, "other"),
    49  		tests: []test{
    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"},
    57  		},
    58  	}, {
    59  		desc: "fractions",
    60  		msg:  Selectf(1, "%.2f", "one", "foo", "other", "bar"),
    61  		tests: []test{
    62  			// fractions are always plural in english
    63  			{arg: 0, result: "bar"},
    64  			{arg: 1, result: "bar"},
    65  		},
    66  	}, {
    67  		desc: "decimal without fractions",
    68  		msg:  Selectf(1, "%.0f", "one", "foo", "other", "bar"),
    69  		tests: []test{
    70  			// fractions are always plural in english
    71  			{arg: 0, result: "bar"},
    72  			{arg: 1, result: "foo"},
    73  		},
    74  	}, {
    75  		desc: "scientific",
    76  		msg:  Selectf(1, "%.0e", "one", "foo", "other", "bar"),
    77  		tests: []test{
    78  			{arg: 0, result: "bar"},
    79  			{arg: 1, result: "foo"},
    80  		},
    81  	}, {
    82  		desc: "variable",
    83  		msg:  Selectf(1, "%.1g", "one", "foo", "other", "bar"),
    84  		tests: []test{
    85  			// fractions are always plural in english
    86  			{arg: 0, result: "bar"},
    87  			{arg: 1, result: "foo"},
    88  			{arg: 2, result: "bar"},
    89  		},
    90  	}, {
    91  		desc: "default",
    92  		msg:  Selectf(1, "", "one", "foo", "other", "bar"),
    93  		tests: []test{
    94  			{arg: 0, result: "bar"},
    95  			{arg: 1, result: "foo"},
    96  			{arg: 2, result: "bar"},
    97  			{arg: 1.0, result: "bar"},
    98  		},
    99  	}, {
   100  		desc: "nested",
   101  		msg:  Selectf(1, "", "other", Selectf(2, "", "one", "foo", "other", "bar")),
   102  		tests: []test{
   103  			{arg: 0, result: "bar"},
   104  			{arg: 1, result: "foo"},
   105  			{arg: 2, result: "bar"},
   106  		},
   107  	}, {
   108  		desc:  "arg unavailable",
   109  		msg:   Selectf(100, "%.2f", "one", "foo", "other", "bar"),
   110  		tests: []test{{arg: 1, result: "bar"}},
   111  	}, {
   112  		desc:  "no match",
   113  		msg:   Selectf(1, "%.2f", "one", "foo"),
   114  		tests: []test{{arg: 0, result: "bar", err: catmsg.ErrNoMatch.Error()}},
   115  	}, {
   116  		desc: "error invalid form",
   117  		err:  `invalid plural form "excessive"`,
   118  		msg:  Selectf(1, "%d", "excessive", "foo"),
   119  	}, {
   120  		desc: "error form not used by language",
   121  		err:  `form "many" not supported for language "en"`,
   122  		msg:  Selectf(1, "%d", "many", "foo"),
   123  	}, {
   124  		desc: "error invalid selector",
   125  		err:  `selector of type int; want string or Form`,
   126  		msg:  Selectf(1, "%d", 1, "foo"),
   127  	}, {
   128  		desc: "error missing message",
   129  		err:  `no message defined for selector one`,
   130  		msg:  Selectf(1, "%d", "one"),
   131  	}, {
   132  		desc: "error invalid number",
   133  		err:  `invalid number in selector "<1.00"`,
   134  		msg:  Selectf(1, "%d", "<1.00"),
   135  	}, {
   136  		desc: "error empty selector",
   137  		err:  `empty selector`,
   138  		msg:  Selectf(1, "%d", "", "foo"),
   139  	}, {
   140  		desc: "error invalid message",
   141  		err:  `message of type int; must be string or catalog.Message`,
   142  		msg:  Selectf(1, "%d", "one", 3),
   143  	}, {
   144  		desc: "nested error",
   145  		err:  `empty selector`,
   146  		msg:  Selectf(1, "", "other", Selectf(2, "", "")),
   147  	}}
   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)
   160  					}
   161  				})
   162  			}
   163  		})
   164  	}
   165  }
   166  
   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)
   171  	}
   172  	if got != nil {
   173  		t.SkipNow()
   174  	}
   175  }
   176  
   177  type renderer struct {
   178  	arg    interface{}
   179  	result string
   180  }
   181  
   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
   185  		return nil
   186  	}
   187  	return r.arg
   188  }
   189  
   190  type opposite int
   191  
   192  func (o opposite) PluralForm(lang language.Tag, scale int) (Form, int) {
   193  	if o == 1 {
   194  		return Other, 1
   195  	}
   196  	return One, int(o)
   197  }
   198  

View as plain text