github.com/mdempsky/go@v0.0.0-20151201204031-5dd372bd1e70/src/text/template/multi_test.go (about) 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. 4 5 package template 6 7 // Tests for mulitple-template parsing and execution. 8 9 import ( 10 "bytes" 11 "fmt" 12 "testing" 13 "text/template/parse" 14 ) 15 16 const ( 17 noError = true 18 hasError = false 19 ) 20 21 type multiParseTest struct { 22 name string 23 input string 24 ok bool 25 names []string 26 results []string 27 } 28 29 var multiParseTests = []multiParseTest{ 30 {"empty", "", noError, 31 nil, 32 nil}, 33 {"one", `{{define "foo"}} FOO {{end}}`, noError, 34 []string{"foo"}, 35 []string{" FOO "}}, 36 {"two", `{{define "foo"}} FOO {{end}}{{define "bar"}} BAR {{end}}`, noError, 37 []string{"foo", "bar"}, 38 []string{" FOO ", " BAR "}}, 39 // errors 40 {"missing end", `{{define "foo"}} FOO `, hasError, 41 nil, 42 nil}, 43 {"malformed name", `{{define "foo}} FOO `, hasError, 44 nil, 45 nil}, 46 } 47 48 func TestMultiParse(t *testing.T) { 49 for _, test := range multiParseTests { 50 template, err := New("root").Parse(test.input) 51 switch { 52 case err == nil && !test.ok: 53 t.Errorf("%q: expected error; got none", test.name) 54 continue 55 case err != nil && test.ok: 56 t.Errorf("%q: unexpected error: %v", test.name, err) 57 continue 58 case err != nil && !test.ok: 59 // expected error, got one 60 if *debug { 61 fmt.Printf("%s: %s\n\t%s\n", test.name, test.input, err) 62 } 63 continue 64 } 65 if template == nil { 66 continue 67 } 68 if len(template.tmpl) != len(test.names)+1 { // +1 for root 69 t.Errorf("%s: wrong number of templates; wanted %d got %d", test.name, len(test.names), len(template.tmpl)) 70 continue 71 } 72 for i, name := range test.names { 73 tmpl, ok := template.tmpl[name] 74 if !ok { 75 t.Errorf("%s: can't find template %q", test.name, name) 76 continue 77 } 78 result := tmpl.Root.String() 79 if result != test.results[i] { 80 t.Errorf("%s=(%q): got\n\t%v\nexpected\n\t%v", test.name, test.input, result, test.results[i]) 81 } 82 } 83 } 84 } 85 86 var multiExecTests = []execTest{ 87 {"empty", "", "", nil, true}, 88 {"text", "some text", "some text", nil, true}, 89 {"invoke x", `{{template "x" .SI}}`, "TEXT", tVal, true}, 90 {"invoke x no args", `{{template "x"}}`, "TEXT", tVal, true}, 91 {"invoke dot int", `{{template "dot" .I}}`, "17", tVal, true}, 92 {"invoke dot []int", `{{template "dot" .SI}}`, "[3 4 5]", tVal, true}, 93 {"invoke dotV", `{{template "dotV" .U}}`, "v", tVal, true}, 94 {"invoke nested int", `{{template "nested" .I}}`, "17", tVal, true}, 95 {"variable declared by template", `{{template "nested" $x:=.SI}},{{index $x 1}}`, "[3 4 5],4", tVal, true}, 96 97 // User-defined function: test argument evaluator. 98 {"testFunc literal", `{{oneArg "joe"}}`, "oneArg=joe", tVal, true}, 99 {"testFunc .", `{{oneArg .}}`, "oneArg=joe", "joe", true}, 100 } 101 102 // These strings are also in testdata/*. 103 const multiText1 = ` 104 {{define "x"}}TEXT{{end}} 105 {{define "dotV"}}{{.V}}{{end}} 106 ` 107 108 const multiText2 = ` 109 {{define "dot"}}{{.}}{{end}} 110 {{define "nested"}}{{template "dot" .}}{{end}} 111 ` 112 113 func TestMultiExecute(t *testing.T) { 114 // Declare a couple of templates first. 115 template, err := New("root").Parse(multiText1) 116 if err != nil { 117 t.Fatalf("parse error for 1: %s", err) 118 } 119 _, err = template.Parse(multiText2) 120 if err != nil { 121 t.Fatalf("parse error for 2: %s", err) 122 } 123 testExecute(multiExecTests, template, t) 124 } 125 126 func TestParseFiles(t *testing.T) { 127 _, err := ParseFiles("DOES NOT EXIST") 128 if err == nil { 129 t.Error("expected error for non-existent file; got none") 130 } 131 template := New("root") 132 _, err = template.ParseFiles("testdata/file1.tmpl", "testdata/file2.tmpl") 133 if err != nil { 134 t.Fatalf("error parsing files: %v", err) 135 } 136 testExecute(multiExecTests, template, t) 137 } 138 139 func TestParseGlob(t *testing.T) { 140 _, err := ParseGlob("DOES NOT EXIST") 141 if err == nil { 142 t.Error("expected error for non-existent file; got none") 143 } 144 _, err = New("error").ParseGlob("[x") 145 if err == nil { 146 t.Error("expected error for bad pattern; got none") 147 } 148 template := New("root") 149 _, err = template.ParseGlob("testdata/file*.tmpl") 150 if err != nil { 151 t.Fatalf("error parsing files: %v", err) 152 } 153 testExecute(multiExecTests, template, t) 154 } 155 156 // In these tests, actual content (not just template definitions) comes from the parsed files. 157 158 var templateFileExecTests = []execTest{ 159 {"test", `{{template "tmpl1.tmpl"}}{{template "tmpl2.tmpl"}}`, "template1\n\ny\ntemplate2\n\nx\n", 0, true}, 160 } 161 162 func TestParseFilesWithData(t *testing.T) { 163 template, err := New("root").ParseFiles("testdata/tmpl1.tmpl", "testdata/tmpl2.tmpl") 164 if err != nil { 165 t.Fatalf("error parsing files: %v", err) 166 } 167 testExecute(templateFileExecTests, template, t) 168 } 169 170 func TestParseGlobWithData(t *testing.T) { 171 template, err := New("root").ParseGlob("testdata/tmpl*.tmpl") 172 if err != nil { 173 t.Fatalf("error parsing files: %v", err) 174 } 175 testExecute(templateFileExecTests, template, t) 176 } 177 178 const ( 179 cloneText1 = `{{define "a"}}{{template "b"}}{{template "c"}}{{end}}` 180 cloneText2 = `{{define "b"}}b{{end}}` 181 cloneText3 = `{{define "c"}}root{{end}}` 182 cloneText4 = `{{define "c"}}clone{{end}}` 183 ) 184 185 func TestClone(t *testing.T) { 186 // Create some templates and clone the root. 187 root, err := New("root").Parse(cloneText1) 188 if err != nil { 189 t.Fatal(err) 190 } 191 _, err = root.Parse(cloneText2) 192 if err != nil { 193 t.Fatal(err) 194 } 195 clone := Must(root.Clone()) 196 // Add variants to both. 197 _, err = root.Parse(cloneText3) 198 if err != nil { 199 t.Fatal(err) 200 } 201 _, err = clone.Parse(cloneText4) 202 if err != nil { 203 t.Fatal(err) 204 } 205 // Verify that the clone is self-consistent. 206 for k, v := range clone.tmpl { 207 if k == clone.name && v.tmpl[k] != clone { 208 t.Error("clone does not contain root") 209 } 210 if v != v.tmpl[v.name] { 211 t.Errorf("clone does not contain self for %q", k) 212 } 213 } 214 // Execute root. 215 var b bytes.Buffer 216 err = root.ExecuteTemplate(&b, "a", 0) 217 if err != nil { 218 t.Fatal(err) 219 } 220 if b.String() != "broot" { 221 t.Errorf("expected %q got %q", "broot", b.String()) 222 } 223 // Execute copy. 224 b.Reset() 225 err = clone.ExecuteTemplate(&b, "a", 0) 226 if err != nil { 227 t.Fatal(err) 228 } 229 if b.String() != "bclone" { 230 t.Errorf("expected %q got %q", "bclone", b.String()) 231 } 232 } 233 234 func TestAddParseTree(t *testing.T) { 235 // Create some templates. 236 root, err := New("root").Parse(cloneText1) 237 if err != nil { 238 t.Fatal(err) 239 } 240 _, err = root.Parse(cloneText2) 241 if err != nil { 242 t.Fatal(err) 243 } 244 // Add a new parse tree. 245 tree, err := parse.Parse("cloneText3", cloneText3, "", "", nil, builtins) 246 if err != nil { 247 t.Fatal(err) 248 } 249 added, err := root.AddParseTree("c", tree["c"]) 250 // Execute. 251 var b bytes.Buffer 252 err = added.ExecuteTemplate(&b, "a", 0) 253 if err != nil { 254 t.Fatal(err) 255 } 256 if b.String() != "broot" { 257 t.Errorf("expected %q got %q", "broot", b.String()) 258 } 259 } 260 261 // Issue 7032 262 func TestAddParseTreeToUnparsedTemplate(t *testing.T) { 263 master := "{{define \"master\"}}{{end}}" 264 tmpl := New("master") 265 tree, err := parse.Parse("master", master, "", "", nil) 266 if err != nil { 267 t.Fatalf("unexpected parse err: %v", err) 268 } 269 masterTree := tree["master"] 270 tmpl.AddParseTree("master", masterTree) // used to panic 271 } 272 273 func TestRedefinition(t *testing.T) { 274 var tmpl *Template 275 var err error 276 if tmpl, err = New("tmpl1").Parse(`{{define "test"}}foo{{end}}`); err != nil { 277 t.Fatalf("parse 1: %v", err) 278 } 279 if _, err = tmpl.Parse(`{{define "test"}}bar{{end}}`); err != nil { 280 t.Fatalf("got error %v, expected nil", err) 281 } 282 if _, err = tmpl.New("tmpl2").Parse(`{{define "test"}}bar{{end}}`); err != nil { 283 t.Fatalf("got error %v, expected nil", err) 284 } 285 } 286 287 // Issue 10879 288 func TestEmptyTemplateCloneCrash(t *testing.T) { 289 t1 := New("base") 290 t1.Clone() // used to panic 291 } 292 293 // Issue 10910, 10926 294 func TestTemplateLookUp(t *testing.T) { 295 t1 := New("foo") 296 if t1.Lookup("foo") != nil { 297 t.Error("Lookup returned non-nil value for undefined template foo") 298 } 299 t1.New("bar") 300 if t1.Lookup("bar") != nil { 301 t.Error("Lookup returned non-nil value for undefined template bar") 302 } 303 t1.Parse(`{{define "foo"}}test{{end}}`) 304 if t1.Lookup("foo") == nil { 305 t.Error("Lookup returned nil value for defined template") 306 } 307 } 308 309 func TestNew(t *testing.T) { 310 // template with same name already exists 311 t1, _ := New("test").Parse(`{{define "test"}}foo{{end}}`) 312 t2 := t1.New("test") 313 314 if t1.common != t2.common { 315 t.Errorf("t1 & t2 didn't share common struct; got %v != %v", t1.common, t2.common) 316 } 317 if t1.Tree == nil { 318 t.Error("defined template got nil Tree") 319 } 320 if t2.Tree != nil { 321 t.Error("undefined template got non-nil Tree") 322 } 323 324 containsT1 := false 325 for _, tmpl := range t1.Templates() { 326 if tmpl == t2 { 327 t.Error("Templates included undefined template") 328 } 329 if tmpl == t1 { 330 containsT1 = true 331 } 332 } 333 if !containsT1 { 334 t.Error("Templates didn't include defined template") 335 } 336 } 337 338 func TestParse(t *testing.T) { 339 // In multiple calls to Parse with the same receiver template, only one call 340 // can contain text other than space, comments, and template definitions 341 t1 := New("test") 342 if _, err := t1.Parse(`{{define "test"}}{{end}}`); err != nil { 343 t.Fatalf("parsing test: %s", err) 344 } 345 if _, err := t1.Parse(`{{define "test"}}{{/* this is a comment */}}{{end}}`); err != nil { 346 t.Fatalf("parsing test: %s", err) 347 } 348 if _, err := t1.Parse(`{{define "test"}}foo{{end}}`); err != nil { 349 t.Fatalf("parsing test: %s", err) 350 } 351 }