aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/template/template_test.go
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2010-12-03 04:34:57 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2010-12-03 04:34:57 +0000
commit7a9389330e91acc3ed05deac2d198af25d13cf3c (patch)
tree38fe54a4f38ede5d949c915d66191f24a6fe5153 /libgo/go/template/template_test.go
parent1aa6700378e5188a853c018256113ce6e1fb5c05 (diff)
downloadgcc-7a9389330e91acc3ed05deac2d198af25d13cf3c.zip
gcc-7a9389330e91acc3ed05deac2d198af25d13cf3c.tar.gz
gcc-7a9389330e91acc3ed05deac2d198af25d13cf3c.tar.bz2
Add Go frontend, libgo library, and Go testsuite.
gcc/: * gcc.c (default_compilers): Add entry for ".go". * common.opt: Add -static-libgo as a driver option. * doc/install.texi (Configuration): Mention libgo as an option for --enable-shared. Mention go as an option for --enable-languages. * doc/invoke.texi (Overall Options): Mention .go as a file name suffix. Mention go as a -x option. * doc/frontends.texi (G++ and GCC): Mention Go as a supported language. * doc/sourcebuild.texi (Top Level): Mention libgo. * doc/standards.texi (Standards): Add section on Go language. Move references for other languages into their own section. * doc/contrib.texi (Contributors): Mention that I contributed the Go frontend. gcc/testsuite/: * lib/go.exp: New file. * lib/go-dg.exp: New file. * lib/go-torture.exp: New file. * lib/target-supports.exp (check_compile): Match // Go. From-SVN: r167407
Diffstat (limited to 'libgo/go/template/template_test.go')
-rw-r--r--libgo/go/template/template_test.go609
1 files changed, 609 insertions, 0 deletions
diff --git a/libgo/go/template/template_test.go b/libgo/go/template/template_test.go
new file mode 100644
index 0000000..00fd69a
--- /dev/null
+++ b/libgo/go/template/template_test.go
@@ -0,0 +1,609 @@
+// 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"
+ "container/vector"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "json"
+ "os"
+ "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
+ integer int
+ raw string
+ innerT T
+ innerPointerT *T
+ data []T
+ pdata []*T
+ empty []*T
+ emptystring string
+ null []*T
+ vec *vector.Vector
+ true bool
+ false bool
+ mp map[string]string
+ json interface{}
+ innermap U
+ stringmap map[string]string
+ bytes []byte
+ 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, interface{}, string) {
+ return func(w io.Writer, v interface{}, format string) {
+ io.WriteString(w, f(v))
+ }
+}
+
+
+var formatters = FormatterMap{
+ "uppercase": writer(uppercase),
+ "+1": writer(plus1),
+}
+
+var tests = []*Test{
+ // Simple
+ &Test{"", "", ""},
+ &Test{"abc", "abc", ""},
+ &Test{"abc\ndef\n", "abc\ndef\n", ""},
+ &Test{" {.meta-left} \n", "{", ""},
+ &Test{" {.meta-right} \n", "}", ""},
+ &Test{" {.space} \n", " ", ""},
+ &Test{" {.tab} \n", "\t", ""},
+ &Test{" {#comment} \n", "", ""},
+ &Test{"\tSome Text\t\n", "\tSome Text\t\n", ""},
+ &Test{" {.meta-right} {.meta-right} {.meta-right} \n", " } } } \n", ""},
+
+ // Variables at top level
+ &Test{
+ in: "{header}={integer}\n",
+
+ out: "Header=77\n",
+ },
+
+ // Method at top level
+ &Test{
+ in: "ptrmethod={pointerMethod}\n",
+
+ out: "ptrmethod=ptrmethod!\n",
+ },
+
+ &Test{
+ in: "valmethod={valueMethod}\n",
+
+ out: "valmethod=valmethod!\n",
+ },
+
+ // Section
+ &Test{
+ in: "{.section data }\n" +
+ "some text for the section\n" +
+ "{.end}\n",
+
+ out: "some text for the section\n",
+ },
+ &Test{
+ in: "{.section data }\n" +
+ "{header}={integer}\n" +
+ "{.end}\n",
+
+ out: "Header=77\n",
+ },
+ &Test{
+ in: "{.section pdata }\n" +
+ "{header}={integer}\n" +
+ "{.end}\n",
+
+ out: "Header=77\n",
+ },
+ &Test{
+ in: "{.section pdata }\n" +
+ "data present\n" +
+ "{.or}\n" +
+ "data not present\n" +
+ "{.end}\n",
+
+ out: "data present\n",
+ },
+ &Test{
+ in: "{.section empty }\n" +
+ "data present\n" +
+ "{.or}\n" +
+ "data not present\n" +
+ "{.end}\n",
+
+ out: "data not present\n",
+ },
+ &Test{
+ in: "{.section null }\n" +
+ "data present\n" +
+ "{.or}\n" +
+ "data not present\n" +
+ "{.end}\n",
+
+ out: "data not present\n",
+ },
+ &Test{
+ in: "{.section pdata }\n" +
+ "{header}={integer}\n" +
+ "{.section @ }\n" +
+ "{header}={integer}\n" +
+ "{.end}\n" +
+ "{.end}\n",
+
+ out: "Header=77\n" +
+ "Header=77\n",
+ },
+
+ &Test{
+ in: "{.section data}{.end} {header}\n",
+
+ out: " Header\n",
+ },
+
+ // Repeated
+ &Test{
+ in: "{.section pdata }\n" +
+ "{.repeated section @ }\n" +
+ "{item}={value}\n" +
+ "{.end}\n" +
+ "{.end}\n",
+
+ out: "ItemNumber1=ValueNumber1\n" +
+ "ItemNumber2=ValueNumber2\n",
+ },
+ &Test{
+ 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",
+ },
+ &Test{
+ 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",
+ },
+ &Test{
+ 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",
+ },
+ &Test{
+ 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",
+ },
+ &Test{
+ 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",
+ },
+ &Test{
+ in: "{.repeated section vec }\n" +
+ "{@}\n" +
+ "{.end}\n",
+
+ out: "elt1\n" +
+ "elt2\n",
+ },
+ // Same but with a space before {.end}: was a bug.
+ &Test{
+ in: "{.repeated section vec }\n" +
+ "{@} {.end}\n",
+
+ out: "elt1 elt2 \n",
+ },
+ &Test{
+ in: "{.repeated section integer}{.end}",
+
+ err: "line 1: .repeated: cannot repeat integer (type int)",
+ },
+
+ // Nested names
+ &Test{
+ in: "{.section @ }\n" +
+ "{innerT.item}={innerT.value}\n" +
+ "{.end}",
+
+ out: "ItemNumber1=ValueNumber1\n",
+ },
+ &Test{
+ in: "{.section @ }\n" +
+ "{innerT.item}={.section innerT}{.section value}{@}{.end}{.end}\n" +
+ "{.end}",
+
+ out: "ItemNumber1=ValueNumber1\n",
+ },
+
+
+ // Formatters
+ &Test{
+ in: "{.section pdata }\n" +
+ "{header|uppercase}={integer|+1}\n" +
+ "{header|html}={integer|str}\n" +
+ "{.end}\n",
+
+ out: "HEADER=78\n" +
+ "Header=77\n",
+ },
+
+ &Test{
+ in: "{raw}\n" +
+ "{raw|html}\n",
+
+ out: "&<>!@ #$%^\n" +
+ "&amp;&lt;&gt;!@ #$%^\n",
+ },
+
+ &Test{
+ in: "{.section emptystring}emptystring{.end}\n" +
+ "{.section header}header{.end}\n",
+
+ out: "\nheader\n",
+ },
+
+ &Test{
+ in: "{.section true}1{.or}2{.end}\n" +
+ "{.section false}3{.or}4{.end}\n",
+
+ out: "1\n4\n",
+ },
+
+ &Test{
+ in: "{bytes}",
+
+ out: "hello",
+ },
+
+ // Maps
+
+ &Test{
+ in: "{mp.mapkey}\n",
+
+ out: "Ahoy!\n",
+ },
+ &Test{
+ in: "{innermap.mp.innerkey}\n",
+
+ out: "55\n",
+ },
+ &Test{
+ in: "{.section innermap}{.section mp}{innerkey}{.end}{.end}\n",
+
+ out: "55\n",
+ },
+ &Test{
+ in: "{.section json}{.repeated section maps}{a}{b}{.end}{.end}\n",
+
+ out: "1234\n",
+ },
+ &Test{
+ in: "{stringmap.stringkey1}\n",
+
+ out: "stringresult\n",
+ },
+ &Test{
+ in: "{.repeated section stringmap}\n" +
+ "{@}\n" +
+ "{.end}",
+
+ out: "stringresult\n" +
+ "stringresult\n",
+ },
+ &Test{
+ in: "{.repeated section stringmap}\n" +
+ "\t{@}\n" +
+ "{.end}",
+
+ out: "\tstringresult\n" +
+ "\tstringresult\n",
+ },
+
+ // Interface values
+
+ &Test{
+ in: "{iface}",
+
+ out: "[1 2 3]",
+ },
+ &Test{
+ in: "{.repeated section iface}{@}{.alternates with} {.end}",
+
+ out: "1 2 3",
+ },
+ &Test{
+ in: "{.section iface}{@}{.end}",
+
+ out: "[1 2 3]",
+ },
+ &Test{
+ in: "{.section ifaceptr}{item} {value}{.end}",
+
+ out: "Item Value",
+ },
+}
+
+func TestAll(t *testing.T) {
+ // Parse
+ testAll(t, func(test *Test) (*Template, os.Error) { return Parse(test.in, formatters) })
+ // ParseFile
+ testAll(t, func(test *Test) (*Template, os.Error) {
+ err := ioutil.WriteFile("_test/test.tmpl", []byte(test.in), 0600)
+ if err != nil {
+ t.Error("unexpected write error:", err)
+ return nil, err
+ }
+ return ParseFile("_test/test.tmpl", formatters)
+ })
+ // tmpl.ParseFile
+ testAll(t, func(test *Test) (*Template, os.Error) {
+ err := ioutil.WriteFile("_test/test.tmpl", []byte(test.in), 0600)
+ if err != nil {
+ t.Error("unexpected write error:", err)
+ return nil, err
+ }
+ tmpl := New(formatters)
+ return tmpl, tmpl.ParseFile("_test/test.tmpl")
+ })
+}
+
+func testAll(t *testing.T, parseFunc func(*Test) (*Template, os.Error)) {
+ s := new(S)
+ // initialized by hand for clarity.
+ s.header = "Header"
+ s.integer = 77
+ s.raw = "&<>!@ #$%^"
+ s.innerT = t1
+ s.data = []T{t1, t2}
+ s.pdata = []*T{&t1, &t2}
+ s.empty = []*T{}
+ s.null = nil
+ s.vec = new(vector.Vector)
+ s.vec.Push("elt1")
+ s.vec.Push("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.bytes = []byte("hello")
+ 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(s, &buf)
+ 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.String() != test.err {
+ t.Errorf("expected execute error %q, got %q", test.err, err.String())
+ }
+ }
+ 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(mp, &b)
+ if err != nil {
+ t.Error("unexpected execute error:", err)
+ }
+ s := b.String()
+ expected := "template: Ahoy!"
+ if s != expected {
+ t.Errorf("failed passing string as data: expected %q got %q", "template: Ahoy!", 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("hello", &b)
+ if err != nil {
+ t.Error("unexpected execute error:", err)
+ }
+ s := b.String()
+ if s != "template: hello" {
+ t.Errorf("failed passing string as data: expected %q got %q", "template: hello", 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("hello", &b)
+ if err != nil {
+ t.Error("unexpected parse error:", err)
+ }
+ s := b.String()
+ text := "template: hello"
+ if s != text {
+ t.Errorf("failed passing string as data: expected %q got %q", text, s)
+ }
+ err = tmpl.Execute("hello", &b)
+ if err != nil {
+ t.Error("unexpected parse error:", err)
+ }
+ s = b.String()
+ text += text
+ if s != text {
+ t.Errorf("failed passing string as data: expected %q got %q", text, 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("hello", &b)
+ 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(s, &buf)
+ 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)
+ }
+}