1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
7 // Tests for mulitple-template parsing and execution.
16 type isEmptyTest struct {
22 var isEmptyTests = []isEmptyTest{
24 {"nonempty", `hello`, false},
25 {"spaces only", " \t\n \t\n", true},
26 {"definition", `{{define "x"}}something{{end}}`, true},
27 {"definitions and space", "{{define `x`}}something{{end}}\n\n{{define `y`}}something{{end}}\n\n", true},
28 {"definitions and text", "{{define `x`}}something{{end}}\nx\n{{define `y`}}something{{end}}\ny\n}}", false},
29 {"definition and action", "{{define `x`}}something{{end}}{{if 3}}foo{{end}}", false},
32 func TestIsEmpty(t *testing.T) {
33 for _, test := range isEmptyTests {
34 template, err := New("root").Parse(test.input)
36 t.Errorf("%q: unexpected error: %v", test.name, err)
39 if empty := isEmpty(template.Root); empty != test.empty {
40 t.Errorf("%q: expected %t got %t", test.name, test.empty, empty)
50 type multiParseTest struct {
58 var multiParseTests = []multiParseTest{
59 {"empty", "", noError,
62 {"one", `{{define "foo"}} FOO {{end}}`, noError,
64 []string{`[(text: " FOO ")]`}},
65 {"two", `{{define "foo"}} FOO {{end}}{{define "bar"}} BAR {{end}}`, noError,
66 []string{"foo", "bar"},
67 []string{`[(text: " FOO ")]`, `[(text: " BAR ")]`}},
69 {"missing end", `{{define "foo"}} FOO `, hasError,
72 {"malformed name", `{{define "foo}} FOO `, hasError,
77 func TestMultiParse(t *testing.T) {
78 for _, test := range multiParseTests {
79 template, err := New("root").Parse(test.input)
81 case err == nil && !test.ok:
82 t.Errorf("%q: expected error; got none", test.name)
84 case err != nil && test.ok:
85 t.Errorf("%q: unexpected error: %v", test.name, err)
87 case err != nil && !test.ok:
88 // expected error, got one
90 fmt.Printf("%s: %s\n\t%s\n", test.name, test.input, err)
97 if len(template.tmpl) != len(test.names)+1 { // +1 for root
98 t.Errorf("%s: wrong number of templates; wanted %d got %d", test.name, len(test.names), len(template.tmpl))
101 for i, name := range test.names {
102 tmpl, ok := template.tmpl[name]
104 t.Errorf("%s: can't find template %q", test.name, name)
107 result := tmpl.Root.String()
108 if result != test.results[i] {
109 t.Errorf("%s=(%q): got\n\t%v\nexpected\n\t%v", test.name, test.input, result, test.results[i])
115 var multiExecTests = []execTest{
116 {"empty", "", "", nil, true},
117 {"text", "some text", "some text", nil, true},
118 {"invoke x", `{{template "x" .SI}}`, "TEXT", tVal, true},
119 {"invoke x no args", `{{template "x"}}`, "TEXT", tVal, true},
120 {"invoke dot int", `{{template "dot" .I}}`, "17", tVal, true},
121 {"invoke dot []int", `{{template "dot" .SI}}`, "[3 4 5]", tVal, true},
122 {"invoke dotV", `{{template "dotV" .U}}`, "v", tVal, true},
123 {"invoke nested int", `{{template "nested" .I}}`, "17", tVal, true},
124 {"variable declared by template", `{{template "nested" $x=.SI}},{{index $x 1}}`, "[3 4 5],4", tVal, true},
126 // User-defined function: test argument evaluator.
127 {"testFunc literal", `{{oneArg "joe"}}`, "oneArg=joe", tVal, true},
128 {"testFunc .", `{{oneArg .}}`, "oneArg=joe", "joe", true},
131 // These strings are also in testdata/*.
133 {{define "x"}}TEXT{{end}}
134 {{define "dotV"}}{{.V}}{{end}}
138 {{define "dot"}}{{.}}{{end}}
139 {{define "nested"}}{{template "dot" .}}{{end}}
142 func TestMultiExecute(t *testing.T) {
143 // Declare a couple of templates first.
144 template, err := New("root").Parse(multiText1)
146 t.Fatalf("parse error for 1: %s", err)
148 _, err = template.Parse(multiText2)
150 t.Fatalf("parse error for 2: %s", err)
152 testExecute(multiExecTests, template, t)
155 func TestParseFiles(t *testing.T) {
156 _, err := ParseFiles("DOES NOT EXIST")
158 t.Error("expected error for non-existent file; got none")
160 template := New("root")
161 _, err = template.ParseFiles("testdata/file1.tmpl", "testdata/file2.tmpl")
163 t.Fatalf("error parsing files: %v", err)
165 testExecute(multiExecTests, template, t)
168 func TestParseGlob(t *testing.T) {
169 _, err := ParseGlob("DOES NOT EXIST")
171 t.Error("expected error for non-existent file; got none")
173 _, err = New("error").ParseGlob("[x")
175 t.Error("expected error for bad pattern; got none")
177 template := New("root")
178 _, err = template.ParseGlob("testdata/file*.tmpl")
180 t.Fatalf("error parsing files: %v", err)
182 testExecute(multiExecTests, template, t)
185 // In these tests, actual content (not just template definitions) comes from the parsed files.
187 var templateFileExecTests = []execTest{
188 {"test", `{{template "tmpl1.tmpl"}}{{template "tmpl2.tmpl"}}`, "template1\n\ny\ntemplate2\n\nx\n", 0, true},
191 func TestParseFilesWithData(t *testing.T) {
192 template, err := New("root").ParseFiles("testdata/tmpl1.tmpl", "testdata/tmpl2.tmpl")
194 t.Fatalf("error parsing files: %v", err)
196 testExecute(templateFileExecTests, template, t)
199 func TestParseGlobWithData(t *testing.T) {
200 template, err := New("root").ParseGlob("testdata/tmpl*.tmpl")
202 t.Fatalf("error parsing files: %v", err)
204 testExecute(templateFileExecTests, template, t)
208 cloneText1 = `{{define "a"}}{{template "b"}}{{template "c"}}{{end}}`
209 cloneText2 = `{{define "b"}}b{{end}}`
210 cloneText3 = `{{define "c"}}root{{end}}`
211 cloneText4 = `{{define "c"}}clone{{end}}`
214 func TestClone(t *testing.T) {
215 // Create some templates and clone the root.
216 root, err := New("root").Parse(cloneText1)
220 _, err = root.Parse(cloneText2)
224 clone := root.Clone()
225 // Add variants to both.
226 _, err = root.Parse(cloneText3)
230 _, err = clone.Parse(cloneText4)
234 // Verify that the clone is self-consistent.
235 for k, v := range clone.tmpl {
236 if k == clone.name && v.tmpl[k] != clone {
237 t.Error("clone does not contain root")
239 if v != v.tmpl[v.name] {
240 t.Errorf("clone does not contain self for %q", k)
245 err = root.ExecuteTemplate(&b, "a", 0)
249 if b.String() != "broot" {
250 t.Errorf("expected %q got %q", "broot", b.String())
254 err = clone.ExecuteTemplate(&b, "a", 0)
258 if b.String() != "bclone" {
259 t.Errorf("expected %q got %q", "bclone", b.String())
263 func TestAddParseTree(t *testing.T) {
264 // Create some templates.
265 root, err := New("root").Parse(cloneText1)
269 _, err = root.Parse(cloneText2)
273 // Add a new parse tree.
274 tree, err := parse.Parse("cloneText3", cloneText3, "", "", nil, builtins)
278 added, err := root.AddParseTree("c", tree["c"])
281 err = added.ExecuteTemplate(&b, "a", 0)
285 if b.String() != "broot" {
286 t.Errorf("expected %q got %q", "broot", b.String())