aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/libgo/go/old/template/template_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/libgo/go/old/template/template_test.go')
-rw-r--r--gcc-4.9/libgo/go/old/template/template_test.go810
1 files changed, 810 insertions, 0 deletions
diff --git a/gcc-4.9/libgo/go/old/template/template_test.go b/gcc-4.9/libgo/go/old/template/template_test.go
new file mode 100644
index 000000000..854a548e5
--- /dev/null
+++ b/gcc-4.9/libgo/go/old/template/template_test.go
@@ -0,0 +1,810 @@
+// Copyright 2009 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 template
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "strings"
+ "testing"
+)
+
+type Test struct {
+ in, out, err string
+}
+
+type T struct {
+ Item string
+ Value string
+}
+
+type U struct {
+ Mp map[string]int
+}
+
+type S struct {
+ Header string
+ HeaderPtr *string
+ Integer int
+ IntegerPtr *int
+ NilPtr *int
+ InnerT T
+ InnerPointerT *T
+ Data []T
+ Pdata []*T
+ Empty []*T
+ Emptystring string
+ Null []*T
+ Vec []interface{}
+ True bool
+ False bool
+ Mp map[string]string
+ JSON interface{}
+ Innermap U
+ Stringmap map[string]string
+ Ptrmap map[string]*string
+ Iface interface{}
+ Ifaceptr interface{}
+}
+
+func (s *S) PointerMethod() string { return "ptrmethod!" }
+
+func (s S) ValueMethod() string { return "valmethod!" }
+
+var t1 = T{"ItemNumber1", "ValueNumber1"}
+var t2 = T{"ItemNumber2", "ValueNumber2"}
+
+func uppercase(v interface{}) string {
+ s := v.(string)
+ t := ""
+ for i := 0; i < len(s); i++ {
+ c := s[i]
+ if 'a' <= c && c <= 'z' {
+ c = c + 'A' - 'a'
+ }
+ t += string(c)
+ }
+ return t
+}
+
+func plus1(v interface{}) string {
+ i := v.(int)
+ return fmt.Sprint(i + 1)
+}
+
+func writer(f func(interface{}) string) func(io.Writer, string, ...interface{}) {
+ return func(w io.Writer, format string, v ...interface{}) {
+ if len(v) != 1 {
+ panic("test writer expected one arg")
+ }
+ io.WriteString(w, f(v[0]))
+ }
+}
+
+func multiword(w io.Writer, format string, value ...interface{}) {
+ for _, v := range value {
+ fmt.Fprintf(w, "<%v>", v)
+ }
+}
+
+func printf(w io.Writer, format string, v ...interface{}) {
+ io.WriteString(w, fmt.Sprintf(v[0].(string), v[1:]...))
+}
+
+var formatters = FormatterMap{
+ "uppercase": writer(uppercase),
+ "+1": writer(plus1),
+ "multiword": multiword,
+ "printf": printf,
+}
+
+var tests = []*Test{
+ // Simple
+ {"", "", ""},
+ {"abc", "abc", ""},
+ {"abc\ndef\n", "abc\ndef\n", ""},
+ {" {.meta-left} \n", "{", ""},
+ {" {.meta-right} \n", "}", ""},
+ {" {.space} \n", " ", ""},
+ {" {.tab} \n", "\t", ""},
+ {" {#comment} \n", "", ""},
+ {"\tSome Text\t\n", "\tSome Text\t\n", ""},
+ {" {.meta-right} {.meta-right} {.meta-right} \n", " } } } \n", ""},
+
+ // Variables at top level
+ {
+ in: "{Header}={Integer}\n",
+
+ out: "Header=77\n",
+ },
+
+ {
+ in: "Pointers: {*HeaderPtr}={*IntegerPtr}\n",
+
+ out: "Pointers: Header=77\n",
+ },
+
+ {
+ in: "Stars but not pointers: {*Header}={*Integer}\n",
+
+ out: "Stars but not pointers: Header=77\n",
+ },
+
+ {
+ in: "nil pointer: {*NilPtr}={*Integer}\n",
+
+ out: "nil pointer: <nil>=77\n",
+ },
+
+ {
+ in: `{"Strings" ":"} {""} {"|"} {"\t\u0123 \x23\\"} {"\"}{\\"}`,
+
+ out: "Strings: | \t\u0123 \x23\\ \"}{\\",
+ },
+
+ {
+ in: "{`Raw strings` `:`} {``} {`|`} {`\\t\\u0123 \\x23\\`} {`}{\\`}",
+
+ out: "Raw strings: | \\t\\u0123 \\x23\\ }{\\",
+ },
+
+ {
+ in: "Characters: {'a'} {'\\u0123'} {' '} {'{'} {'|'} {'}'}",
+
+ out: "Characters: 97 291 32 123 124 125",
+ },
+
+ {
+ in: "Integers: {1} {-2} {+42} {0777} {0x0a}",
+
+ out: "Integers: 1 -2 42 511 10",
+ },
+
+ {
+ in: "Floats: {.5} {-.5} {1.1} {-2.2} {+42.1} {1e10} {1.2e-3} {1.2e3} {-1.2e3}",
+
+ out: "Floats: 0.5 -0.5 1.1 -2.2 42.1 1e+10 0.0012 1200 -1200",
+ },
+
+ // Method at top level
+ {
+ in: "ptrmethod={PointerMethod}\n",
+
+ out: "ptrmethod=ptrmethod!\n",
+ },
+
+ {
+ in: "valmethod={ValueMethod}\n",
+
+ out: "valmethod=valmethod!\n",
+ },
+
+ // Section
+ {
+ in: "{.section Data }\n" +
+ "some text for the section\n" +
+ "{.end}\n",
+
+ out: "some text for the section\n",
+ },
+ {
+ in: "{.section Data }\n" +
+ "{Header}={Integer}\n" +
+ "{.end}\n",
+
+ out: "Header=77\n",
+ },
+ {
+ in: "{.section Pdata }\n" +
+ "{Header}={Integer}\n" +
+ "{.end}\n",
+
+ out: "Header=77\n",
+ },
+ {
+ in: "{.section Pdata }\n" +
+ "data present\n" +
+ "{.or}\n" +
+ "data not present\n" +
+ "{.end}\n",
+
+ out: "data present\n",
+ },
+ {
+ in: "{.section Empty }\n" +
+ "data present\n" +
+ "{.or}\n" +
+ "data not present\n" +
+ "{.end}\n",
+
+ out: "data not present\n",
+ },
+ {
+ in: "{.section Null }\n" +
+ "data present\n" +
+ "{.or}\n" +
+ "data not present\n" +
+ "{.end}\n",
+
+ out: "data not present\n",
+ },
+ {
+ in: "{.section Pdata }\n" +
+ "{Header}={Integer}\n" +
+ "{.section @ }\n" +
+ "{Header}={Integer}\n" +
+ "{.end}\n" +
+ "{.end}\n",
+
+ out: "Header=77\n" +
+ "Header=77\n",
+ },
+
+ {
+ in: "{.section Data}{.end} {Header}\n",
+
+ out: " Header\n",
+ },
+
+ {
+ in: "{.section Integer}{@}{.end}",
+
+ out: "77",
+ },
+
+ // Repeated
+ {
+ in: "{.section Pdata }\n" +
+ "{.repeated section @ }\n" +
+ "{Item}={Value}\n" +
+ "{.end}\n" +
+ "{.end}\n",
+
+ out: "ItemNumber1=ValueNumber1\n" +
+ "ItemNumber2=ValueNumber2\n",
+ },
+ {
+ in: "{.section Pdata }\n" +
+ "{.repeated section @ }\n" +
+ "{Item}={Value}\n" +
+ "{.or}\n" +
+ "this should not appear\n" +
+ "{.end}\n" +
+ "{.end}\n",
+
+ out: "ItemNumber1=ValueNumber1\n" +
+ "ItemNumber2=ValueNumber2\n",
+ },
+ {
+ in: "{.section @ }\n" +
+ "{.repeated section Empty }\n" +
+ "{Item}={Value}\n" +
+ "{.or}\n" +
+ "this should appear: empty field\n" +
+ "{.end}\n" +
+ "{.end}\n",
+
+ out: "this should appear: empty field\n",
+ },
+ {
+ in: "{.repeated section Pdata }\n" +
+ "{Item}\n" +
+ "{.alternates with}\n" +
+ "is\nover\nmultiple\nlines\n" +
+ "{.end}\n",
+
+ out: "ItemNumber1\n" +
+ "is\nover\nmultiple\nlines\n" +
+ "ItemNumber2\n",
+ },
+ {
+ in: "{.repeated section Pdata }\n" +
+ "{Item}\n" +
+ "{.alternates with}\n" +
+ "is\nover\nmultiple\nlines\n" +
+ " {.end}\n",
+
+ out: "ItemNumber1\n" +
+ "is\nover\nmultiple\nlines\n" +
+ "ItemNumber2\n",
+ },
+ {
+ in: "{.section Pdata }\n" +
+ "{.repeated section @ }\n" +
+ "{Item}={Value}\n" +
+ "{.alternates with}DIVIDER\n" +
+ "{.or}\n" +
+ "this should not appear\n" +
+ "{.end}\n" +
+ "{.end}\n",
+
+ out: "ItemNumber1=ValueNumber1\n" +
+ "DIVIDER\n" +
+ "ItemNumber2=ValueNumber2\n",
+ },
+ {
+ in: "{.repeated section Vec }\n" +
+ "{@}\n" +
+ "{.end}\n",
+
+ out: "elt1\n" +
+ "elt2\n",
+ },
+ // Same but with a space before {.end}: was a bug.
+ {
+ in: "{.repeated section Vec }\n" +
+ "{@} {.end}\n",
+
+ out: "elt1 elt2 \n",
+ },
+ {
+ in: "{.repeated section Integer}{.end}",
+
+ err: "line 1: .repeated: cannot repeat Integer (type int)",
+ },
+
+ // Nested names
+ {
+ in: "{.section @ }\n" +
+ "{InnerT.Item}={InnerT.Value}\n" +
+ "{.end}",
+
+ out: "ItemNumber1=ValueNumber1\n",
+ },
+ {
+ in: "{.section @ }\n" +
+ "{InnerT.Item}={.section InnerT}{.section Value}{@}{.end}{.end}\n" +
+ "{.end}",
+
+ out: "ItemNumber1=ValueNumber1\n",
+ },
+
+ {
+ in: "{.section Emptystring}emptystring{.end}\n" +
+ "{.section Header}header{.end}\n",
+
+ out: "\nheader\n",
+ },
+
+ {
+ in: "{.section True}1{.or}2{.end}\n" +
+ "{.section False}3{.or}4{.end}\n",
+
+ out: "1\n4\n",
+ },
+
+ // Maps
+
+ {
+ in: "{Mp.mapkey}\n",
+
+ out: "Ahoy!\n",
+ },
+ {
+ in: "{Innermap.Mp.innerkey}\n",
+
+ out: "55\n",
+ },
+ {
+ in: "{.section Innermap}{.section Mp}{innerkey}{.end}{.end}\n",
+
+ out: "55\n",
+ },
+ {
+ in: "{.section JSON}{.repeated section maps}{a}{b}{.end}{.end}\n",
+
+ out: "1234\n",
+ },
+ {
+ in: "{Stringmap.stringkey1}\n",
+
+ out: "stringresult\n",
+ },
+ {
+ in: "{.repeated section Stringmap}\n" +
+ "{@}\n" +
+ "{.end}",
+
+ out: "stringresult\n" +
+ "stringresult\n",
+ },
+ {
+ in: "{.repeated section Stringmap}\n" +
+ "\t{@}\n" +
+ "{.end}",
+
+ out: "\tstringresult\n" +
+ "\tstringresult\n",
+ },
+ {
+ in: "{*Ptrmap.stringkey1}\n",
+
+ out: "pointedToString\n",
+ },
+ {
+ in: "{.repeated section Ptrmap}\n" +
+ "{*@}\n" +
+ "{.end}",
+
+ out: "pointedToString\n" +
+ "pointedToString\n",
+ },
+
+ // Interface values
+
+ {
+ in: "{Iface}",
+
+ out: "[1 2 3]",
+ },
+ {
+ in: "{.repeated section Iface}{@}{.alternates with} {.end}",
+
+ out: "1 2 3",
+ },
+ {
+ in: "{.section Iface}{@}{.end}",
+
+ out: "[1 2 3]",
+ },
+ {
+ in: "{.section Ifaceptr}{Item} {Value}{.end}",
+
+ out: "Item Value",
+ },
+}
+
+func TestAll(t *testing.T) {
+ // Parse
+ testAll(t, func(test *Test) (*Template, error) { return Parse(test.in, formatters) })
+ // ParseFile
+ f, err := ioutil.TempFile("", "template-test")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer func() {
+ name := f.Name()
+ f.Close()
+ os.Remove(name)
+ }()
+ testAll(t, func(test *Test) (*Template, error) {
+ err := ioutil.WriteFile(f.Name(), []byte(test.in), 0600)
+ if err != nil {
+ t.Error("unexpected write error:", err)
+ return nil, err
+ }
+ return ParseFile(f.Name(), formatters)
+ })
+ // tmpl.ParseFile
+ testAll(t, func(test *Test) (*Template, error) {
+ err := ioutil.WriteFile(f.Name(), []byte(test.in), 0600)
+ if err != nil {
+ t.Error("unexpected write error:", err)
+ return nil, err
+ }
+ tmpl := New(formatters)
+ return tmpl, tmpl.ParseFile(f.Name())
+ })
+}
+
+func testAll(t *testing.T, parseFunc func(*Test) (*Template, error)) {
+ s := new(S)
+ // initialized by hand for clarity.
+ s.Header = "Header"
+ s.HeaderPtr = &s.Header
+ s.Integer = 77
+ s.IntegerPtr = &s.Integer
+ s.InnerT = t1
+ s.Data = []T{t1, t2}
+ s.Pdata = []*T{&t1, &t2}
+ s.Empty = []*T{}
+ s.Null = nil
+ s.Vec = []interface{}{"elt1", "elt2"}
+ s.True = true
+ s.False = false
+ s.Mp = make(map[string]string)
+ s.Mp["mapkey"] = "Ahoy!"
+ json.Unmarshal([]byte(`{"maps":[{"a":1,"b":2},{"a":3,"b":4}]}`), &s.JSON)
+ s.Innermap.Mp = make(map[string]int)
+ s.Innermap.Mp["innerkey"] = 55
+ s.Stringmap = make(map[string]string)
+ s.Stringmap["stringkey1"] = "stringresult" // the same value so repeated section is order-independent
+ s.Stringmap["stringkey2"] = "stringresult"
+ s.Ptrmap = make(map[string]*string)
+ x := "pointedToString"
+ s.Ptrmap["stringkey1"] = &x // the same value so repeated section is order-independent
+ s.Ptrmap["stringkey2"] = &x
+ s.Iface = []int{1, 2, 3}
+ s.Ifaceptr = &T{"Item", "Value"}
+
+ var buf bytes.Buffer
+ for _, test := range tests {
+ buf.Reset()
+ tmpl, err := parseFunc(test)
+ if err != nil {
+ t.Error("unexpected parse error: ", err)
+ continue
+ }
+ err = tmpl.Execute(&buf, s)
+ if test.err == "" {
+ if err != nil {
+ t.Error("unexpected execute error:", err)
+ }
+ } else {
+ if err == nil {
+ t.Errorf("expected execute error %q, got nil", test.err)
+ } else if err.Error() != test.err {
+ t.Errorf("expected execute error %q, got %q", test.err, err.Error())
+ }
+ }
+ if buf.String() != test.out {
+ t.Errorf("for %q: expected %q got %q", test.in, test.out, buf.String())
+ }
+ }
+}
+
+func TestMapDriverType(t *testing.T) {
+ mp := map[string]string{"footer": "Ahoy!"}
+ tmpl, err := Parse("template: {footer}", nil)
+ if err != nil {
+ t.Error("unexpected parse error:", err)
+ }
+ var b bytes.Buffer
+ err = tmpl.Execute(&b, mp)
+ if err != nil {
+ t.Error("unexpected execute error:", err)
+ }
+ s := b.String()
+ expect := "template: Ahoy!"
+ if s != expect {
+ t.Errorf("failed passing string as data: expected %q got %q", expect, s)
+ }
+}
+
+func TestMapNoEntry(t *testing.T) {
+ mp := make(map[string]int)
+ tmpl, err := Parse("template: {notthere}!", nil)
+ if err != nil {
+ t.Error("unexpected parse error:", err)
+ }
+ var b bytes.Buffer
+ err = tmpl.Execute(&b, mp)
+ if err != nil {
+ t.Error("unexpected execute error:", err)
+ }
+ s := b.String()
+ expect := "template: 0!"
+ if s != expect {
+ t.Errorf("failed passing string as data: expected %q got %q", expect, s)
+ }
+}
+
+func TestStringDriverType(t *testing.T) {
+ tmpl, err := Parse("template: {@}", nil)
+ if err != nil {
+ t.Error("unexpected parse error:", err)
+ }
+ var b bytes.Buffer
+ err = tmpl.Execute(&b, "hello")
+ if err != nil {
+ t.Error("unexpected execute error:", err)
+ }
+ s := b.String()
+ expect := "template: hello"
+ if s != expect {
+ t.Errorf("failed passing string as data: expected %q got %q", expect, s)
+ }
+}
+
+func TestTwice(t *testing.T) {
+ tmpl, err := Parse("template: {@}", nil)
+ if err != nil {
+ t.Error("unexpected parse error:", err)
+ }
+ var b bytes.Buffer
+ err = tmpl.Execute(&b, "hello")
+ if err != nil {
+ t.Error("unexpected parse error:", err)
+ }
+ s := b.String()
+ expect := "template: hello"
+ if s != expect {
+ t.Errorf("failed passing string as data: expected %q got %q", expect, s)
+ }
+ err = tmpl.Execute(&b, "hello")
+ if err != nil {
+ t.Error("unexpected parse error:", err)
+ }
+ s = b.String()
+ expect += expect
+ if s != expect {
+ t.Errorf("failed passing string as data: expected %q got %q", expect, s)
+ }
+}
+
+func TestCustomDelims(t *testing.T) {
+ // try various lengths. zero should catch error.
+ for i := 0; i < 7; i++ {
+ for j := 0; j < 7; j++ {
+ tmpl := New(nil)
+ // first two chars deliberately the same to test equal left and right delims
+ ldelim := "$!#$%^&"[0:i]
+ rdelim := "$*&^%$!"[0:j]
+ tmpl.SetDelims(ldelim, rdelim)
+ // if braces, this would be template: {@}{.meta-left}{.meta-right}
+ text := "template: " +
+ ldelim + "@" + rdelim +
+ ldelim + ".meta-left" + rdelim +
+ ldelim + ".meta-right" + rdelim
+ err := tmpl.Parse(text)
+ if err != nil {
+ if i == 0 || j == 0 { // expected
+ continue
+ }
+ t.Error("unexpected parse error:", err)
+ } else if i == 0 || j == 0 {
+ t.Errorf("expected parse error for empty delimiter: %d %d %q %q", i, j, ldelim, rdelim)
+ continue
+ }
+ var b bytes.Buffer
+ err = tmpl.Execute(&b, "hello")
+ s := b.String()
+ if s != "template: hello"+ldelim+rdelim {
+ t.Errorf("failed delim check(%q %q) %q got %q", ldelim, rdelim, text, s)
+ }
+ }
+ }
+}
+
+// Test that a variable evaluates to the field itself and does not further indirection
+func TestVarIndirection(t *testing.T) {
+ s := new(S)
+ // initialized by hand for clarity.
+ s.InnerPointerT = &t1
+
+ var buf bytes.Buffer
+ input := "{.section @}{InnerPointerT}{.end}"
+ tmpl, err := Parse(input, nil)
+ if err != nil {
+ t.Fatal("unexpected parse error:", err)
+ }
+ err = tmpl.Execute(&buf, s)
+ if err != nil {
+ t.Fatal("unexpected execute error:", err)
+ }
+ expect := fmt.Sprintf("%v", &t1) // output should be hex address of t1
+ if buf.String() != expect {
+ t.Errorf("for %q: expected %q got %q", input, expect, buf.String())
+ }
+}
+
+func TestHTMLFormatterWithByte(t *testing.T) {
+ s := "Test string."
+ b := []byte(s)
+ var buf bytes.Buffer
+ HTMLFormatter(&buf, "", b)
+ bs := buf.String()
+ if bs != s {
+ t.Errorf("munged []byte, expected: %s got: %s", s, bs)
+ }
+}
+
+type UF struct {
+ I int
+ s string
+}
+
+func TestReferenceToUnexported(t *testing.T) {
+ u := &UF{3, "hello"}
+ var buf bytes.Buffer
+ input := "{.section @}{I}{s}{.end}"
+ tmpl, err := Parse(input, nil)
+ if err != nil {
+ t.Fatal("unexpected parse error:", err)
+ }
+ err = tmpl.Execute(&buf, u)
+ if err == nil {
+ t.Fatal("expected execute error, got none")
+ }
+ if strings.Index(err.Error(), "not exported") < 0 {
+ t.Fatal("expected unexported error; got", err)
+ }
+}
+
+var formatterTests = []Test{
+ {
+ in: "{Header|uppercase}={Integer|+1}\n" +
+ "{Header|html}={Integer|str}\n",
+
+ out: "HEADER=78\n" +
+ "Header=77\n",
+ },
+
+ {
+ in: "{Header|uppercase}={Integer Header|multiword}\n" +
+ "{Header|html}={Header Integer|multiword}\n" +
+ "{Header|html}={Header Integer}\n",
+
+ out: "HEADER=<77><Header>\n" +
+ "Header=<Header><77>\n" +
+ "Header=Header77\n",
+ },
+ {
+ in: "{Raw}\n" +
+ "{Raw|html}\n",
+
+ out: "a <&> b\n" +
+ "a &lt;&amp;&gt; b\n",
+ },
+ {
+ in: "{Bytes}",
+ out: "hello",
+ },
+ {
+ in: "{Raw|uppercase|html|html}",
+ out: "A &amp;lt;&amp;amp;&amp;gt; B",
+ },
+ {
+ in: "{Header Integer|multiword|html}",
+ out: "&lt;Header&gt;&lt;77&gt;",
+ },
+ {
+ in: "{Integer|no_formatter|html}",
+ err: `unknown formatter: "no_formatter"`,
+ },
+ {
+ in: "{Integer|||||}", // empty string is a valid formatter
+ out: "77",
+ },
+ {
+ in: `{"%.02f 0x%02X" 1.1 10|printf}`,
+ out: "1.10 0x0A",
+ },
+ {
+ in: `{""|}{""||}{""|printf}`, // Issue #1896.
+ out: "",
+ },
+}
+
+func TestFormatters(t *testing.T) {
+ data := map[string]interface{}{
+ "Header": "Header",
+ "Integer": 77,
+ "Raw": "a <&> b",
+ "Bytes": []byte("hello"),
+ }
+ for _, c := range formatterTests {
+ tmpl, err := Parse(c.in, formatters)
+ if err != nil {
+ if c.err == "" {
+ t.Error("unexpected parse error:", err)
+ continue
+ }
+ if strings.Index(err.Error(), c.err) < 0 {
+ t.Errorf("unexpected error: expected %q, got %q", c.err, err.Error())
+ continue
+ }
+ } else {
+ if c.err != "" {
+ t.Errorf("For %q, expected error, got none.", c.in)
+ continue
+ }
+ var buf bytes.Buffer
+ err = tmpl.Execute(&buf, data)
+ if err != nil {
+ t.Error("unexpected Execute error: ", err)
+ continue
+ }
+ actual := buf.String()
+ if actual != c.out {
+ t.Errorf("for %q: expected %q but got %q.", c.in, c.out, actual)
+ }
+ }
+ }
+}