diff options
Diffstat (limited to 'src/pkg/template/template_test.go')
| -rw-r--r-- | src/pkg/template/template_test.go | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/src/pkg/template/template_test.go b/src/pkg/template/template_test.go new file mode 100644 index 000000000..9a81d274c --- /dev/null +++ b/src/pkg/template/template_test.go @@ -0,0 +1,331 @@ +// 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 ( + "fmt"; + "io"; + "os"; + "reflect"; + "template"; + "testing"; +) + +type Test struct { + in, out string +} + +type T struct { + item string; + value string; +} + +type S struct { + header string; + integer int; + raw string; + data []T; + pdata []*T; + empty []*T; + emptystring string; + null []*T; +} + +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\ndef\n", "abc\ndef\n" }, + &Test{ " {.meta-left} \n", "{" }, + &Test{ " {.meta-right} \n", "}" }, + &Test{ " {.space} \n", " " }, + &Test{ " {.tab} \n", "\t" }, + &Test{ " {#comment} \n", "" }, + + // Variables at top level + &Test{ + "{header}={integer}\n", + + "Header=77\n" + }, + + // Section + &Test{ + "{.section data }\n" + "some text for the section\n" + "{.end}\n", + + "some text for the section\n" + }, + &Test{ + "{.section data }\n" + "{header}={integer}\n" + "{.end}\n", + + "Header=77\n" + }, + &Test{ + "{.section pdata }\n" + "{header}={integer}\n" + "{.end}\n", + + "Header=77\n" + }, + &Test{ + "{.section pdata }\n" + "data present\n" + "{.or}\n" + "data not present\n" + "{.end}\n", + + "data present\n" + }, + &Test{ + "{.section empty }\n" + "data present\n" + "{.or}\n" + "data not present\n" + "{.end}\n", + + "data not present\n" + }, + &Test{ + "{.section null }\n" + "data present\n" + "{.or}\n" + "data not present\n" + "{.end}\n", + + "data not present\n" + }, + &Test{ + "{.section pdata }\n" + "{header}={integer}\n" + "{.section @ }\n" + "{header}={integer}\n" + "{.end}\n" + "{.end}\n", + + "Header=77\n" + "Header=77\n" + }, + &Test{ + "{.section data}{.end} {header}\n", + + " Header\n" + }, + + // Repeated + &Test{ + "{.section pdata }\n" + "{.repeated section @ }\n" + "{item}={value}\n" + "{.end}\n" + "{.end}\n", + + "ItemNumber1=ValueNumber1\n" + "ItemNumber2=ValueNumber2\n" + }, + &Test{ + "{.section pdata }\n" + "{.repeated section @ }\n" + "{item}={value}\n" + "{.or}\n" + "this should not appear\n" + "{.end}\n" + "{.end}\n", + + "ItemNumber1=ValueNumber1\n" + "ItemNumber2=ValueNumber2\n" + }, + &Test{ + "{.section @ }\n" + "{.repeated section empty }\n" + "{item}={value}\n" + "{.or}\n" + "this should appear: empty field\n" + "{.end}\n" + "{.end}\n", + + "this should appear: empty field\n" + }, + &Test{ + "{.section pdata }\n" + "{.repeated section @ }\n" + "{item}={value}\n" + "{.alternates with}DIVIDER\n" + "{.or}\n" + "this should not appear\n" + "{.end}\n" + "{.end}\n", + + "ItemNumber1=ValueNumber1\n" + "DIVIDER\n" + "ItemNumber2=ValueNumber2\n" + }, + + // Formatters + &Test{ + "{.section pdata }\n" + "{header|uppercase}={integer|+1}\n" + "{header|html}={integer|str}\n" + "{.end}\n", + + "HEADER=78\n" + "Header=77\n" + }, + + &Test{ + "{raw}\n" + "{raw|html}\n", + + "&<>!@ #$%^\n" + "&<>!@ #$%^\n" + }, + + &Test{ + "{.section emptystring}emptystring{.end}\n" + "{.section header}header{.end}\n", + + "\nheader\n" + }, +} + +func TestAll(t *testing.T) { + s := new(S); + // initialized by hand for clarity. + s.header = "Header"; + s.integer = 77; + s.raw = "&<>!@ #$%^"; + s.data = []T{ t1, t2 }; + s.pdata = []*T{ &t1, &t2 }; + s.empty = []*T{ }; + s.null = nil; + + var buf io.ByteBuffer; + for i, test := range tests { + buf.Reset(); + tmpl, err := Parse(test.in, formatters); + if err != nil { + t.Error("unexpected parse error:", err); + continue; + } + err = tmpl.Execute(s, &buf); + if err != nil { + t.Error("unexpected execute error:", err) + } + if string(buf.Data()) != test.out { + t.Errorf("for %q: expected %q got %q", test.in, test.out, string(buf.Data())); + } + } +} + +func TestStringDriverType(t *testing.T) { + tmpl, err := Parse("template: {@}", nil); + if err != nil { + t.Error("unexpected parse error:", err) + } + var b io.ByteBuffer; + err = tmpl.Execute("hello", &b); + if err != nil { + t.Error("unexpected execute error:", err) + } + s := string(b.Data()); + 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 io.ByteBuffer; + err = tmpl.Execute("hello", &b); + if err != nil { + t.Error("unexpected parse error:", err) + } + s := string(b.Data()); + 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 = string(b.Data()); + 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 io.ByteBuffer; + err = tmpl.Execute("hello", &b); + s := string(b.Data()); + if s != "template: hello" + ldelim + rdelim { + t.Errorf("failed delim check(%q %q) %q got %q", ldelim, rdelim, text, s) + } + } + } +} |
