summaryrefslogtreecommitdiff
path: root/vendor/golang.org/x/text/internal/catmsg/catmsg_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/text/internal/catmsg/catmsg_test.go')
-rw-r--r--vendor/golang.org/x/text/internal/catmsg/catmsg_test.go316
1 files changed, 316 insertions, 0 deletions
diff --git a/vendor/golang.org/x/text/internal/catmsg/catmsg_test.go b/vendor/golang.org/x/text/internal/catmsg/catmsg_test.go
new file mode 100644
index 0000000..485d19c
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/catmsg/catmsg_test.go
@@ -0,0 +1,316 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package catmsg
+
+import (
+ "errors"
+ "strings"
+ "testing"
+
+ "golang.org/x/text/language"
+)
+
+type renderer struct {
+ args []int
+ result string
+}
+
+func (r *renderer) Arg(i int) interface{} {
+ if i >= len(r.args) {
+ return nil
+ }
+ return r.args[i]
+}
+
+func (r *renderer) Render(s string) {
+ if r.result != "" {
+ r.result += "|"
+ }
+ r.result += s
+}
+
+func TestCodec(t *testing.T) {
+ type test struct {
+ args []int
+ out string
+ decErr string
+ }
+ single := func(out, err string) []test { return []test{{out: out, decErr: err}} }
+ testCases := []struct {
+ desc string
+ m Message
+ enc string
+ encErr string
+ tests []test
+ }{{
+ desc: "unused variable",
+ m: &Var{"name", String("foo")},
+ encErr: errIsVar.Error(),
+ tests: single("", ""),
+ }, {
+ desc: "empty",
+ m: empty{},
+ tests: single("", ""),
+ }, {
+ desc: "sequence with empty",
+ m: seq{empty{}},
+ tests: single("", ""),
+ }, {
+ desc: "raw string",
+ m: Raw("foo"),
+ tests: single("foo", ""),
+ }, {
+ desc: "raw string no sub",
+ m: Raw("${foo}"),
+ enc: "\x02${foo}",
+ tests: single("${foo}", ""),
+ }, {
+ desc: "simple string",
+ m: String("foo"),
+ tests: single("foo", ""),
+ }, {
+ desc: "missing var",
+ m: String("foo${bar}"),
+ enc: "\x03\x03foo\x02\x03bar",
+ encErr: `unknown var "bar"`,
+ tests: single("foo|bar", ""),
+ }, {
+ desc: "empty var",
+ m: seq{
+ &Var{"bar", seq{}},
+ String("foo${bar}"),
+ },
+ enc: "\x00\x05\x04\x02bar\x03\x03foo\x00\x00",
+ // TODO: recognize that it is cheaper to substitute bar.
+ tests: single("foo|bar", ""),
+ }, {
+ desc: "var after value",
+ m: seq{
+ String("foo${bar}"),
+ &Var{"bar", String("baz")},
+ },
+ encErr: errIsVar.Error(),
+ tests: single("foo|bar", ""),
+ }, {
+ desc: "substitution",
+ m: seq{
+ &Var{"bar", String("baz")},
+ String("foo${bar}"),
+ },
+ tests: single("foo|baz", ""),
+ }, {
+ desc: "shadowed variable",
+ m: seq{
+ &Var{"bar", String("baz")},
+ seq{
+ &Var{"bar", String("BAZ")},
+ String("foo${bar}"),
+ },
+ },
+ tests: single("foo|BAZ", ""),
+ }, {
+ desc: "nested value",
+ m: nestedLang{nestedLang{empty{}}},
+ tests: single("nl|nl", ""),
+ }, {
+ desc: "not shadowed variable",
+ m: seq{
+ &Var{"bar", String("baz")},
+ seq{
+ String("foo${bar}"),
+ &Var{"bar", String("BAZ")},
+ },
+ },
+ encErr: errIsVar.Error(),
+ tests: single("foo|baz", ""),
+ }, {
+ desc: "duplicate variable",
+ m: seq{
+ &Var{"bar", String("baz")},
+ &Var{"bar", String("BAZ")},
+ String("${bar}"),
+ },
+ encErr: "catmsg: duplicate variable \"bar\"",
+ tests: single("baz", ""),
+ }, {
+ desc: "complete incomplete variable",
+ m: seq{
+ &Var{"bar", incomplete{}},
+ String("${bar}"),
+ },
+ enc: "\x00\t\b\x01\x01\x04\x04\x02bar\x03\x00\x00\x00",
+ // TODO: recognize that it is cheaper to substitute bar.
+ tests: single("bar", ""),
+ }, {
+ desc: "incomplete sequence",
+ m: seq{
+ incomplete{},
+ incomplete{},
+ },
+ encErr: ErrIncomplete.Error(),
+ tests: single("", ErrNoMatch.Error()),
+ }, {
+ desc: "compile error variable",
+ m: seq{
+ &Var{"bar", errorCompileMsg{}},
+ String("${bar}"),
+ },
+ encErr: errCompileTest.Error(),
+ tests: single("bar", ""),
+ }, {
+ desc: "compile error message",
+ m: errorCompileMsg{},
+ encErr: errCompileTest.Error(),
+ tests: single("", ""),
+ }, {
+ desc: "compile error sequence",
+ m: seq{
+ errorCompileMsg{},
+ errorCompileMsg{},
+ },
+ encErr: errCompileTest.Error(),
+ tests: single("", ""),
+ }, {
+ desc: "macro",
+ m: String("${exists(1)}"),
+ tests: single("you betya!", ""),
+ }, {
+ desc: "macro incomplete",
+ m: String("${incomplete(1)}"),
+ enc: "\x03\x00\x01\nincomplete\x01",
+ tests: single("incomplete", ""),
+ }, {
+ desc: "macro undefined at end",
+ m: String("${undefined(1)}"),
+ enc: "\x03\x00\x01\tundefined\x01",
+ tests: single("undefined", "catmsg: undefined macro \"undefined\""),
+ }, {
+ desc: "macro undefined with more text following",
+ m: String("${undefined(1)}."),
+ enc: "\x03\x00\x01\tundefined\x01\x01.",
+ tests: single("undefined|.", "catmsg: undefined macro \"undefined\""),
+ }, {
+ desc: "macro missing paren",
+ m: String("${missing(1}"),
+ encErr: "catmsg: missing ')'",
+ tests: single("$!(MISSINGPAREN)", ""),
+ }, {
+ desc: "macro bad num",
+ m: String("aa${bad(a)}"),
+ encErr: "catmsg: invalid number \"a\"",
+ tests: single("aa$!(BADNUM)", ""),
+ }, {
+ desc: "var missing brace",
+ m: String("a${missing"),
+ encErr: "catmsg: missing '}'",
+ tests: single("a$!(MISSINGBRACE)", ""),
+ }}
+ r := &renderer{}
+ dec := NewDecoder(language.Und, r, macros)
+ for _, tc := range testCases {
+ t.Run(tc.desc, func(t *testing.T) {
+ // Use a language other than Und so that we can test
+ // passing the language to nested values.
+ data, err := Compile(language.Dutch, macros, tc.m)
+ if failErr(err, tc.encErr) {
+ t.Errorf("encoding error: got %+q; want %+q", err, tc.encErr)
+ }
+ if tc.enc != "" && data != tc.enc {
+ t.Errorf("encoding: got %+q; want %+q", data, tc.enc)
+ }
+ for _, st := range tc.tests {
+ t.Run("", func(t *testing.T) {
+ *r = renderer{args: st.args}
+ if err = dec.Execute(data); failErr(err, st.decErr) {
+ t.Errorf("decoding error: got %+q; want %+q", err, st.decErr)
+ }
+ if r.result != st.out {
+ t.Errorf("decode: got %+q; want %+q", r.result, st.out)
+ }
+ })
+ }
+ })
+ }
+}
+
+func failErr(got error, want string) bool {
+ if got == nil {
+ return want != ""
+ }
+ return want == "" || !strings.Contains(got.Error(), want)
+}
+
+type seq []Message
+
+func (s seq) Compile(e *Encoder) (err error) {
+ err = ErrIncomplete
+ e.EncodeMessageType(msgFirst)
+ for _, m := range s {
+ // Pass only the last error, but allow erroneous or complete messages
+ // here to allow testing different scenarios.
+ err = e.EncodeMessage(m)
+ }
+ return err
+}
+
+type empty struct{}
+
+func (empty) Compile(e *Encoder) (err error) { return nil }
+
+var msgIncomplete = Register(
+ "golang.org/x/text/internal/catmsg.incomplete",
+ func(d *Decoder) bool { return false })
+
+type incomplete struct{}
+
+func (incomplete) Compile(e *Encoder) (err error) {
+ e.EncodeMessageType(msgIncomplete)
+ return ErrIncomplete
+}
+
+var msgNested = Register(
+ "golang.org/x/text/internal/catmsg.nested",
+ func(d *Decoder) bool {
+ d.Render(d.DecodeString())
+ d.ExecuteMessage()
+ return true
+ })
+
+type nestedLang struct{ Message }
+
+func (n nestedLang) Compile(e *Encoder) (err error) {
+ e.EncodeMessageType(msgNested)
+ e.EncodeString(e.Language().String())
+ e.EncodeMessage(n.Message)
+ return nil
+}
+
+type errorCompileMsg struct{}
+
+var errCompileTest = errors.New("catmsg: compile error test")
+
+func (errorCompileMsg) Compile(e *Encoder) (err error) {
+ return errCompileTest
+}
+
+type dictionary struct{}
+
+var (
+ macros = dictionary{}
+ dictMessages = map[string]string{
+ "exists": compile(String("you betya!")),
+ "incomplete": compile(incomplete{}),
+ }
+)
+
+func (d dictionary) Lookup(key string) (data string, ok bool) {
+ data, ok = dictMessages[key]
+ return
+}
+
+func compile(m Message) (data string) {
+ data, _ = Compile(language.Und, macros, m)
+ return data
+}