From 554fd8c5195424bdbcabf5de30fdc183aba391bd Mon Sep 17 00:00:00 2001 From: upstream source tree Date: Sun, 15 Mar 2015 20:14:05 -0400 Subject: obtained gcc-4.6.4.tar.bz2 from upstream website; verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository. --- libgo/go/template/template_test.go | 660 +++++++++++++++++++++++++++++++++++++ 1 file changed, 660 insertions(+) create mode 100644 libgo/go/template/template_test.go (limited to 'libgo/go/template/template_test.go') diff --git a/libgo/go/template/template_test.go b/libgo/go/template/template_test.go new file mode 100644 index 000000000..57f297e8f --- /dev/null +++ b/libgo/go/template/template_test.go @@ -0,0 +1,660 @@ +// 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" + "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 + 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, 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) + } +} + +var formatters = FormatterMap{ + "uppercase": writer(uppercase), + "+1": writer(plus1), + "multiword": multiword, +} + +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", + }, + + &Test{ + in: "{.section Integer}{@}{.end}", + + out: "77", + }, + + + // 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: "{.section Pdata }\n" + + "{Header|uppercase}={Integer Header|multiword}\n" + + "{Header|html}={Header Integer|multiword}\n" + + "{Header|html}={Header Integer}\n" + + "{.end}\n", + + out: "HEADER=<77>
\n" + + "Header=
<77>\n" + + "Header=Header77\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) + } +} + +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(u, &buf) + if err == nil { + t.Fatal("expected execute error, got none") + } + if strings.Index(err.String(), "not exported") < 0 { + t.Fatal("expected unexported error; got", err) + } +} -- cgit v1.2.3