diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2010-12-03 04:34:57 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2010-12-03 04:34:57 +0000 |
commit | 7a9389330e91acc3ed05deac2d198af25d13cf3c (patch) | |
tree | 38fe54a4f38ede5d949c915d66191f24a6fe5153 /libgo/go/template/template_test.go | |
parent | 1aa6700378e5188a853c018256113ce6e1fb5c05 (diff) | |
download | gcc-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.go | 609 |
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" + + "&<>!@ #$%^\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) + } +} |