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