github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/text/template/exec_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 import ( 8 "bytes" 9 "errors" 10 "flag" 11 "fmt" 12 "io/ioutil" 13 "reflect" 14 "strings" 15 "testing" 16 ) 17 18 var debug = flag.Bool("debug", false, "show the errors produced by the tests") 19 20 // T has lots of interesting pieces to use to test execution. 21 type T struct { 22 // Basics 23 True bool 24 I int 25 U16 uint16 26 X string 27 FloatZero float64 28 ComplexZero complex128 29 // Nested structs. 30 U *U 31 // Struct with String method. 32 V0 V 33 V1, V2 *V 34 // Struct with Error method. 35 W0 W 36 W1, W2 *W 37 // Slices 38 SI []int 39 SIEmpty []int 40 SB []bool 41 // Maps 42 MSI map[string]int 43 MSIone map[string]int // one element, for deterministic output 44 MSIEmpty map[string]int 45 MXI map[interface{}]int 46 MII map[int]int 47 MI32S map[int32]string 48 MI64S map[int64]string 49 MUI32S map[uint32]string 50 MUI64S map[uint64]string 51 MI8S map[int8]string 52 MUI8S map[uint8]string 53 SMSI []map[string]int 54 // Empty interfaces; used to see if we can dig inside one. 55 Empty0 interface{} // nil 56 Empty1 interface{} 57 Empty2 interface{} 58 Empty3 interface{} 59 Empty4 interface{} 60 // Non-empty interfaces. 61 NonEmptyInterface I 62 NonEmptyInterfacePtS *I 63 // Stringer. 64 Str fmt.Stringer 65 Err error 66 // Pointers 67 PI *int 68 PS *string 69 PSI *[]int 70 NIL *int 71 // Function (not method) 72 BinaryFunc func(string, string) string 73 VariadicFunc func(...string) string 74 VariadicFuncInt func(int, ...string) string 75 NilOKFunc func(*int) bool 76 ErrFunc func() (string, error) 77 PanicFunc func() string 78 // Template to test evaluation of templates. 79 Tmpl *Template 80 // Unexported field; cannot be accessed by template. 81 unexported int 82 } 83 84 type S []string 85 86 func (S) Method0() string { 87 return "M0" 88 } 89 90 type U struct { 91 V string 92 } 93 94 type V struct { 95 j int 96 } 97 98 func (v *V) String() string { 99 if v == nil { 100 return "nilV" 101 } 102 return fmt.Sprintf("<%d>", v.j) 103 } 104 105 type W struct { 106 k int 107 } 108 109 func (w *W) Error() string { 110 if w == nil { 111 return "nilW" 112 } 113 return fmt.Sprintf("[%d]", w.k) 114 } 115 116 var siVal = I(S{"a", "b"}) 117 118 var tVal = &T{ 119 True: true, 120 I: 17, 121 U16: 16, 122 X: "x", 123 U: &U{"v"}, 124 V0: V{6666}, 125 V1: &V{7777}, // leave V2 as nil 126 W0: W{888}, 127 W1: &W{999}, // leave W2 as nil 128 SI: []int{3, 4, 5}, 129 SB: []bool{true, false}, 130 MSI: map[string]int{"one": 1, "two": 2, "three": 3}, 131 MSIone: map[string]int{"one": 1}, 132 MXI: map[interface{}]int{"one": 1}, 133 MII: map[int]int{1: 1}, 134 MI32S: map[int32]string{1: "one", 2: "two"}, 135 MI64S: map[int64]string{2: "i642", 3: "i643"}, 136 MUI32S: map[uint32]string{2: "u322", 3: "u323"}, 137 MUI64S: map[uint64]string{2: "ui642", 3: "ui643"}, 138 MI8S: map[int8]string{2: "i82", 3: "i83"}, 139 MUI8S: map[uint8]string{2: "u82", 3: "u83"}, 140 SMSI: []map[string]int{ 141 {"one": 1, "two": 2}, 142 {"eleven": 11, "twelve": 12}, 143 }, 144 Empty1: 3, 145 Empty2: "empty2", 146 Empty3: []int{7, 8}, 147 Empty4: &U{"UinEmpty"}, 148 NonEmptyInterface: &T{X: "x"}, 149 NonEmptyInterfacePtS: &siVal, 150 Str: bytes.NewBuffer([]byte("foozle")), 151 Err: errors.New("erroozle"), 152 PI: newInt(23), 153 PS: newString("a string"), 154 PSI: newIntSlice(21, 22, 23), 155 BinaryFunc: func(a, b string) string { return fmt.Sprintf("[%s=%s]", a, b) }, 156 VariadicFunc: func(s ...string) string { return fmt.Sprint("<", strings.Join(s, "+"), ">") }, 157 VariadicFuncInt: func(a int, s ...string) string { return fmt.Sprint(a, "=<", strings.Join(s, "+"), ">") }, 158 NilOKFunc: func(s *int) bool { return s == nil }, 159 ErrFunc: func() (string, error) { return "bla", nil }, 160 PanicFunc: func() string { panic("test panic") }, 161 Tmpl: Must(New("x").Parse("test template")), // "x" is the value of .X 162 } 163 164 var tSliceOfNil = []*T{nil} 165 166 // A non-empty interface. 167 type I interface { 168 Method0() string 169 } 170 171 var iVal I = tVal 172 173 // Helpers for creation. 174 func newInt(n int) *int { 175 return &n 176 } 177 178 func newString(s string) *string { 179 return &s 180 } 181 182 func newIntSlice(n ...int) *[]int { 183 p := new([]int) 184 *p = make([]int, len(n)) 185 copy(*p, n) 186 return p 187 } 188 189 // Simple methods with and without arguments. 190 func (t *T) Method0() string { 191 return "M0" 192 } 193 194 func (t *T) Method1(a int) int { 195 return a 196 } 197 198 func (t *T) Method2(a uint16, b string) string { 199 return fmt.Sprintf("Method2: %d %s", a, b) 200 } 201 202 func (t *T) Method3(v interface{}) string { 203 return fmt.Sprintf("Method3: %v", v) 204 } 205 206 func (t *T) Copy() *T { 207 n := new(T) 208 *n = *t 209 return n 210 } 211 212 func (t *T) MAdd(a int, b []int) []int { 213 v := make([]int, len(b)) 214 for i, x := range b { 215 v[i] = x + a 216 } 217 return v 218 } 219 220 var myError = errors.New("my error") 221 222 // MyError returns a value and an error according to its argument. 223 func (t *T) MyError(error bool) (bool, error) { 224 if error { 225 return true, myError 226 } 227 return false, nil 228 } 229 230 // A few methods to test chaining. 231 func (t *T) GetU() *U { 232 return t.U 233 } 234 235 func (u *U) TrueFalse(b bool) string { 236 if b { 237 return "true" 238 } 239 return "" 240 } 241 242 func typeOf(arg interface{}) string { 243 return fmt.Sprintf("%T", arg) 244 } 245 246 type execTest struct { 247 name string 248 input string 249 output string 250 data interface{} 251 ok bool 252 } 253 254 // bigInt and bigUint are hex string representing numbers either side 255 // of the max int boundary. 256 // We do it this way so the test doesn't depend on ints being 32 bits. 257 var ( 258 bigInt = fmt.Sprintf("0x%x", int(1<<uint(reflect.TypeOf(0).Bits()-1)-1)) 259 bigUint = fmt.Sprintf("0x%x", uint(1<<uint(reflect.TypeOf(0).Bits()-1))) 260 ) 261 262 var execTests = []execTest{ 263 // Trivial cases. 264 {"empty", "", "", nil, true}, 265 {"text", "some text", "some text", nil, true}, 266 {"nil action", "{{nil}}", "", nil, false}, 267 268 // Ideal constants. 269 {"ideal int", "{{typeOf 3}}", "int", 0, true}, 270 {"ideal float", "{{typeOf 1.0}}", "float64", 0, true}, 271 {"ideal exp float", "{{typeOf 1e1}}", "float64", 0, true}, 272 {"ideal complex", "{{typeOf 1i}}", "complex128", 0, true}, 273 {"ideal int", "{{typeOf " + bigInt + "}}", "int", 0, true}, 274 {"ideal too big", "{{typeOf " + bigUint + "}}", "", 0, false}, 275 {"ideal nil without type", "{{nil}}", "", 0, false}, 276 277 // Fields of structs. 278 {".X", "-{{.X}}-", "-x-", tVal, true}, 279 {".U.V", "-{{.U.V}}-", "-v-", tVal, true}, 280 {".unexported", "{{.unexported}}", "", tVal, false}, 281 282 // Fields on maps. 283 {"map .one", "{{.MSI.one}}", "1", tVal, true}, 284 {"map .two", "{{.MSI.two}}", "2", tVal, true}, 285 {"map .NO", "{{.MSI.NO}}", "<no value>", tVal, true}, 286 {"map .one interface", "{{.MXI.one}}", "1", tVal, true}, 287 {"map .WRONG args", "{{.MSI.one 1}}", "", tVal, false}, 288 {"map .WRONG type", "{{.MII.one}}", "", tVal, false}, 289 290 // Dots of all kinds to test basic evaluation. 291 {"dot int", "<{{.}}>", "<13>", 13, true}, 292 {"dot uint", "<{{.}}>", "<14>", uint(14), true}, 293 {"dot float", "<{{.}}>", "<15.1>", 15.1, true}, 294 {"dot bool", "<{{.}}>", "<true>", true, true}, 295 {"dot complex", "<{{.}}>", "<(16.2-17i)>", 16.2 - 17i, true}, 296 {"dot string", "<{{.}}>", "<hello>", "hello", true}, 297 {"dot slice", "<{{.}}>", "<[-1 -2 -3]>", []int{-1, -2, -3}, true}, 298 {"dot map", "<{{.}}>", "<map[two:22]>", map[string]int{"two": 22}, true}, 299 {"dot struct", "<{{.}}>", "<{7 seven}>", struct { 300 a int 301 b string 302 }{7, "seven"}, true}, 303 304 // Variables. 305 {"$ int", "{{$}}", "123", 123, true}, 306 {"$.I", "{{$.I}}", "17", tVal, true}, 307 {"$.U.V", "{{$.U.V}}", "v", tVal, true}, 308 {"declare in action", "{{$x := $.U.V}}{{$x}}", "v", tVal, true}, 309 {"simple assignment", "{{$x := 2}}{{$x = 3}}{{$x}}", "3", tVal, true}, 310 {"nested assignment", 311 "{{$x := 2}}{{if true}}{{$x = 3}}{{end}}{{$x}}", 312 "3", tVal, true}, 313 {"nested assignment changes the last declaration", 314 "{{$x := 1}}{{if true}}{{$x := 2}}{{if true}}{{$x = 3}}{{end}}{{end}}{{$x}}", 315 "1", tVal, true}, 316 317 // Type with String method. 318 {"V{6666}.String()", "-{{.V0}}-", "-<6666>-", tVal, true}, 319 {"&V{7777}.String()", "-{{.V1}}-", "-<7777>-", tVal, true}, 320 {"(*V)(nil).String()", "-{{.V2}}-", "-nilV-", tVal, true}, 321 322 // Type with Error method. 323 {"W{888}.Error()", "-{{.W0}}-", "-[888]-", tVal, true}, 324 {"&W{999}.Error()", "-{{.W1}}-", "-[999]-", tVal, true}, 325 {"(*W)(nil).Error()", "-{{.W2}}-", "-nilW-", tVal, true}, 326 327 // Pointers. 328 {"*int", "{{.PI}}", "23", tVal, true}, 329 {"*string", "{{.PS}}", "a string", tVal, true}, 330 {"*[]int", "{{.PSI}}", "[21 22 23]", tVal, true}, 331 {"*[]int[1]", "{{index .PSI 1}}", "22", tVal, true}, 332 {"NIL", "{{.NIL}}", "<nil>", tVal, true}, 333 334 // Empty interfaces holding values. 335 {"empty nil", "{{.Empty0}}", "<no value>", tVal, true}, 336 {"empty with int", "{{.Empty1}}", "3", tVal, true}, 337 {"empty with string", "{{.Empty2}}", "empty2", tVal, true}, 338 {"empty with slice", "{{.Empty3}}", "[7 8]", tVal, true}, 339 {"empty with struct", "{{.Empty4}}", "{UinEmpty}", tVal, true}, 340 {"empty with struct, field", "{{.Empty4.V}}", "UinEmpty", tVal, true}, 341 342 // Edge cases with <no value> with an interface value 343 {"field on interface", "{{.foo}}", "<no value>", nil, true}, 344 {"field on parenthesized interface", "{{(.).foo}}", "<no value>", nil, true}, 345 346 // Method calls. 347 {".Method0", "-{{.Method0}}-", "-M0-", tVal, true}, 348 {".Method1(1234)", "-{{.Method1 1234}}-", "-1234-", tVal, true}, 349 {".Method1(.I)", "-{{.Method1 .I}}-", "-17-", tVal, true}, 350 {".Method2(3, .X)", "-{{.Method2 3 .X}}-", "-Method2: 3 x-", tVal, true}, 351 {".Method2(.U16, `str`)", "-{{.Method2 .U16 `str`}}-", "-Method2: 16 str-", tVal, true}, 352 {".Method2(.U16, $x)", "{{if $x := .X}}-{{.Method2 .U16 $x}}{{end}}-", "-Method2: 16 x-", tVal, true}, 353 {".Method3(nil constant)", "-{{.Method3 nil}}-", "-Method3: <nil>-", tVal, true}, 354 {".Method3(nil value)", "-{{.Method3 .MXI.unset}}-", "-Method3: <nil>-", tVal, true}, 355 {"method on var", "{{if $x := .}}-{{$x.Method2 .U16 $x.X}}{{end}}-", "-Method2: 16 x-", tVal, true}, 356 {"method on chained var", 357 "{{range .MSIone}}{{if $.U.TrueFalse $.True}}{{$.U.TrueFalse $.True}}{{else}}WRONG{{end}}{{end}}", 358 "true", tVal, true}, 359 {"chained method", 360 "{{range .MSIone}}{{if $.GetU.TrueFalse $.True}}{{$.U.TrueFalse $.True}}{{else}}WRONG{{end}}{{end}}", 361 "true", tVal, true}, 362 {"chained method on variable", 363 "{{with $x := .}}{{with .SI}}{{$.GetU.TrueFalse $.True}}{{end}}{{end}}", 364 "true", tVal, true}, 365 {".NilOKFunc not nil", "{{call .NilOKFunc .PI}}", "false", tVal, true}, 366 {".NilOKFunc nil", "{{call .NilOKFunc nil}}", "true", tVal, true}, 367 {"method on nil value from slice", "-{{range .}}{{.Method1 1234}}{{end}}-", "-1234-", tSliceOfNil, true}, 368 369 // Function call builtin. 370 {".BinaryFunc", "{{call .BinaryFunc `1` `2`}}", "[1=2]", tVal, true}, 371 {".VariadicFunc0", "{{call .VariadicFunc}}", "<>", tVal, true}, 372 {".VariadicFunc2", "{{call .VariadicFunc `he` `llo`}}", "<he+llo>", tVal, true}, 373 {".VariadicFuncInt", "{{call .VariadicFuncInt 33 `he` `llo`}}", "33=<he+llo>", tVal, true}, 374 {"if .BinaryFunc call", "{{ if .BinaryFunc}}{{call .BinaryFunc `1` `2`}}{{end}}", "[1=2]", tVal, true}, 375 {"if not .BinaryFunc call", "{{ if not .BinaryFunc}}{{call .BinaryFunc `1` `2`}}{{else}}No{{end}}", "No", tVal, true}, 376 {"Interface Call", `{{stringer .S}}`, "foozle", map[string]interface{}{"S": bytes.NewBufferString("foozle")}, true}, 377 {".ErrFunc", "{{call .ErrFunc}}", "bla", tVal, true}, 378 {"call nil", "{{call nil}}", "", tVal, false}, 379 380 // Erroneous function calls (check args). 381 {".BinaryFuncTooFew", "{{call .BinaryFunc `1`}}", "", tVal, false}, 382 {".BinaryFuncTooMany", "{{call .BinaryFunc `1` `2` `3`}}", "", tVal, false}, 383 {".BinaryFuncBad0", "{{call .BinaryFunc 1 3}}", "", tVal, false}, 384 {".BinaryFuncBad1", "{{call .BinaryFunc `1` 3}}", "", tVal, false}, 385 {".VariadicFuncBad0", "{{call .VariadicFunc 3}}", "", tVal, false}, 386 {".VariadicFuncIntBad0", "{{call .VariadicFuncInt}}", "", tVal, false}, 387 {".VariadicFuncIntBad`", "{{call .VariadicFuncInt `x`}}", "", tVal, false}, 388 {".VariadicFuncNilBad", "{{call .VariadicFunc nil}}", "", tVal, false}, 389 390 // Pipelines. 391 {"pipeline", "-{{.Method0 | .Method2 .U16}}-", "-Method2: 16 M0-", tVal, true}, 392 {"pipeline func", "-{{call .VariadicFunc `llo` | call .VariadicFunc `he` }}-", "-<he+<llo>>-", tVal, true}, 393 394 // Nil values aren't missing arguments. 395 {"nil pipeline", "{{ .Empty0 | call .NilOKFunc }}", "true", tVal, true}, 396 {"nil call arg", "{{ call .NilOKFunc .Empty0 }}", "true", tVal, true}, 397 {"bad nil pipeline", "{{ .Empty0 | .VariadicFunc }}", "", tVal, false}, 398 399 // Parenthesized expressions 400 {"parens in pipeline", "{{printf `%d %d %d` (1) (2 | add 3) (add 4 (add 5 6))}}", "1 5 15", tVal, true}, 401 402 // Parenthesized expressions with field accesses 403 {"parens: $ in paren", "{{($).X}}", "x", tVal, true}, 404 {"parens: $.GetU in paren", "{{($.GetU).V}}", "v", tVal, true}, 405 {"parens: $ in paren in pipe", "{{($ | echo).X}}", "x", tVal, true}, 406 {"parens: spaces and args", `{{(makemap "up" "down" "left" "right").left}}`, "right", tVal, true}, 407 408 // If. 409 {"if true", "{{if true}}TRUE{{end}}", "TRUE", tVal, true}, 410 {"if false", "{{if false}}TRUE{{else}}FALSE{{end}}", "FALSE", tVal, true}, 411 {"if nil", "{{if nil}}TRUE{{end}}", "", tVal, false}, 412 {"if 1", "{{if 1}}NON-ZERO{{else}}ZERO{{end}}", "NON-ZERO", tVal, true}, 413 {"if 0", "{{if 0}}NON-ZERO{{else}}ZERO{{end}}", "ZERO", tVal, true}, 414 {"if 1.5", "{{if 1.5}}NON-ZERO{{else}}ZERO{{end}}", "NON-ZERO", tVal, true}, 415 {"if 0.0", "{{if .FloatZero}}NON-ZERO{{else}}ZERO{{end}}", "ZERO", tVal, true}, 416 {"if 1.5i", "{{if 1.5i}}NON-ZERO{{else}}ZERO{{end}}", "NON-ZERO", tVal, true}, 417 {"if 0.0i", "{{if .ComplexZero}}NON-ZERO{{else}}ZERO{{end}}", "ZERO", tVal, true}, 418 {"if emptystring", "{{if ``}}NON-EMPTY{{else}}EMPTY{{end}}", "EMPTY", tVal, true}, 419 {"if string", "{{if `notempty`}}NON-EMPTY{{else}}EMPTY{{end}}", "NON-EMPTY", tVal, true}, 420 {"if emptyslice", "{{if .SIEmpty}}NON-EMPTY{{else}}EMPTY{{end}}", "EMPTY", tVal, true}, 421 {"if slice", "{{if .SI}}NON-EMPTY{{else}}EMPTY{{end}}", "NON-EMPTY", tVal, true}, 422 {"if emptymap", "{{if .MSIEmpty}}NON-EMPTY{{else}}EMPTY{{end}}", "EMPTY", tVal, true}, 423 {"if map", "{{if .MSI}}NON-EMPTY{{else}}EMPTY{{end}}", "NON-EMPTY", tVal, true}, 424 {"if map unset", "{{if .MXI.none}}NON-ZERO{{else}}ZERO{{end}}", "ZERO", tVal, true}, 425 {"if map not unset", "{{if not .MXI.none}}ZERO{{else}}NON-ZERO{{end}}", "ZERO", tVal, true}, 426 {"if $x with $y int", "{{if $x := true}}{{with $y := .I}}{{$x}},{{$y}}{{end}}{{end}}", "true,17", tVal, true}, 427 {"if $x with $x int", "{{if $x := true}}{{with $x := .I}}{{$x}},{{end}}{{$x}}{{end}}", "17,true", tVal, true}, 428 {"if else if", "{{if false}}FALSE{{else if true}}TRUE{{end}}", "TRUE", tVal, true}, 429 {"if else chain", "{{if eq 1 3}}1{{else if eq 2 3}}2{{else if eq 3 3}}3{{end}}", "3", tVal, true}, 430 431 // Print etc. 432 {"print", `{{print "hello, print"}}`, "hello, print", tVal, true}, 433 {"print 123", `{{print 1 2 3}}`, "1 2 3", tVal, true}, 434 {"print nil", `{{print nil}}`, "<nil>", tVal, true}, 435 {"println", `{{println 1 2 3}}`, "1 2 3\n", tVal, true}, 436 {"printf int", `{{printf "%04x" 127}}`, "007f", tVal, true}, 437 {"printf float", `{{printf "%g" 3.5}}`, "3.5", tVal, true}, 438 {"printf complex", `{{printf "%g" 1+7i}}`, "(1+7i)", tVal, true}, 439 {"printf string", `{{printf "%s" "hello"}}`, "hello", tVal, true}, 440 {"printf function", `{{printf "%#q" zeroArgs}}`, "`zeroArgs`", tVal, true}, 441 {"printf field", `{{printf "%s" .U.V}}`, "v", tVal, true}, 442 {"printf method", `{{printf "%s" .Method0}}`, "M0", tVal, true}, 443 {"printf dot", `{{with .I}}{{printf "%d" .}}{{end}}`, "17", tVal, true}, 444 {"printf var", `{{with $x := .I}}{{printf "%d" $x}}{{end}}`, "17", tVal, true}, 445 {"printf lots", `{{printf "%d %s %g %s" 127 "hello" 7-3i .Method0}}`, "127 hello (7-3i) M0", tVal, true}, 446 447 // HTML. 448 {"html", `{{html "<script>alert(\"XSS\");</script>"}}`, 449 "<script>alert("XSS");</script>", nil, true}, 450 {"html pipeline", `{{printf "<script>alert(\"XSS\");</script>" | html}}`, 451 "<script>alert("XSS");</script>", nil, true}, 452 {"html", `{{html .PS}}`, "a string", tVal, true}, 453 {"html typed nil", `{{html .NIL}}`, "<nil>", tVal, true}, 454 {"html untyped nil", `{{html .Empty0}}`, "<no value>", tVal, true}, 455 456 // JavaScript. 457 {"js", `{{js .}}`, `It\'d be nice.`, `It'd be nice.`, true}, 458 459 // URL query. 460 {"urlquery", `{{"http://www.example.org/"|urlquery}}`, "http%3A%2F%2Fwww.example.org%2F", nil, true}, 461 462 // Booleans 463 {"not", "{{not true}} {{not false}}", "false true", nil, true}, 464 {"and", "{{and false 0}} {{and 1 0}} {{and 0 true}} {{and 1 1}}", "false 0 0 1", nil, true}, 465 {"or", "{{or 0 0}} {{or 1 0}} {{or 0 true}} {{or 1 1}}", "0 1 true 1", nil, true}, 466 {"boolean if", "{{if and true 1 `hi`}}TRUE{{else}}FALSE{{end}}", "TRUE", tVal, true}, 467 {"boolean if not", "{{if and true 1 `hi` | not}}TRUE{{else}}FALSE{{end}}", "FALSE", nil, true}, 468 469 // Indexing. 470 {"slice[0]", "{{index .SI 0}}", "3", tVal, true}, 471 {"slice[1]", "{{index .SI 1}}", "4", tVal, true}, 472 {"slice[HUGE]", "{{index .SI 10}}", "", tVal, false}, 473 {"slice[WRONG]", "{{index .SI `hello`}}", "", tVal, false}, 474 {"slice[nil]", "{{index .SI nil}}", "", tVal, false}, 475 {"map[one]", "{{index .MSI `one`}}", "1", tVal, true}, 476 {"map[two]", "{{index .MSI `two`}}", "2", tVal, true}, 477 {"map[NO]", "{{index .MSI `XXX`}}", "0", tVal, true}, 478 {"map[nil]", "{{index .MSI nil}}", "", tVal, false}, 479 {"map[``]", "{{index .MSI ``}}", "0", tVal, true}, 480 {"map[WRONG]", "{{index .MSI 10}}", "", tVal, false}, 481 {"double index", "{{index .SMSI 1 `eleven`}}", "11", tVal, true}, 482 {"nil[1]", "{{index nil 1}}", "", tVal, false}, 483 {"map MI64S", "{{index .MI64S 2}}", "i642", tVal, true}, 484 {"map MI32S", "{{index .MI32S 2}}", "two", tVal, true}, 485 {"map MUI64S", "{{index .MUI64S 3}}", "ui643", tVal, true}, 486 {"map MI8S", "{{index .MI8S 3}}", "i83", tVal, true}, 487 {"map MUI8S", "{{index .MUI8S 2}}", "u82", tVal, true}, 488 489 // Len. 490 {"slice", "{{len .SI}}", "3", tVal, true}, 491 {"map", "{{len .MSI }}", "3", tVal, true}, 492 {"len of int", "{{len 3}}", "", tVal, false}, 493 {"len of nothing", "{{len .Empty0}}", "", tVal, false}, 494 495 // With. 496 {"with true", "{{with true}}{{.}}{{end}}", "true", tVal, true}, 497 {"with false", "{{with false}}{{.}}{{else}}FALSE{{end}}", "FALSE", tVal, true}, 498 {"with 1", "{{with 1}}{{.}}{{else}}ZERO{{end}}", "1", tVal, true}, 499 {"with 0", "{{with 0}}{{.}}{{else}}ZERO{{end}}", "ZERO", tVal, true}, 500 {"with 1.5", "{{with 1.5}}{{.}}{{else}}ZERO{{end}}", "1.5", tVal, true}, 501 {"with 0.0", "{{with .FloatZero}}{{.}}{{else}}ZERO{{end}}", "ZERO", tVal, true}, 502 {"with 1.5i", "{{with 1.5i}}{{.}}{{else}}ZERO{{end}}", "(0+1.5i)", tVal, true}, 503 {"with 0.0i", "{{with .ComplexZero}}{{.}}{{else}}ZERO{{end}}", "ZERO", tVal, true}, 504 {"with emptystring", "{{with ``}}{{.}}{{else}}EMPTY{{end}}", "EMPTY", tVal, true}, 505 {"with string", "{{with `notempty`}}{{.}}{{else}}EMPTY{{end}}", "notempty", tVal, true}, 506 {"with emptyslice", "{{with .SIEmpty}}{{.}}{{else}}EMPTY{{end}}", "EMPTY", tVal, true}, 507 {"with slice", "{{with .SI}}{{.}}{{else}}EMPTY{{end}}", "[3 4 5]", tVal, true}, 508 {"with emptymap", "{{with .MSIEmpty}}{{.}}{{else}}EMPTY{{end}}", "EMPTY", tVal, true}, 509 {"with map", "{{with .MSIone}}{{.}}{{else}}EMPTY{{end}}", "map[one:1]", tVal, true}, 510 {"with empty interface, struct field", "{{with .Empty4}}{{.V}}{{end}}", "UinEmpty", tVal, true}, 511 {"with $x int", "{{with $x := .I}}{{$x}}{{end}}", "17", tVal, true}, 512 {"with $x struct.U.V", "{{with $x := $}}{{$x.U.V}}{{end}}", "v", tVal, true}, 513 {"with variable and action", "{{with $x := $}}{{$y := $.U.V}}{{$y}}{{end}}", "v", tVal, true}, 514 515 // Range. 516 {"range []int", "{{range .SI}}-{{.}}-{{end}}", "-3--4--5-", tVal, true}, 517 {"range empty no else", "{{range .SIEmpty}}-{{.}}-{{end}}", "", tVal, true}, 518 {"range []int else", "{{range .SI}}-{{.}}-{{else}}EMPTY{{end}}", "-3--4--5-", tVal, true}, 519 {"range empty else", "{{range .SIEmpty}}-{{.}}-{{else}}EMPTY{{end}}", "EMPTY", tVal, true}, 520 {"range []bool", "{{range .SB}}-{{.}}-{{end}}", "-true--false-", tVal, true}, 521 {"range []int method", "{{range .SI | .MAdd .I}}-{{.}}-{{end}}", "-20--21--22-", tVal, true}, 522 {"range map", "{{range .MSI}}-{{.}}-{{end}}", "-1--3--2-", tVal, true}, 523 {"range empty map no else", "{{range .MSIEmpty}}-{{.}}-{{end}}", "", tVal, true}, 524 {"range map else", "{{range .MSI}}-{{.}}-{{else}}EMPTY{{end}}", "-1--3--2-", tVal, true}, 525 {"range empty map else", "{{range .MSIEmpty}}-{{.}}-{{else}}EMPTY{{end}}", "EMPTY", tVal, true}, 526 {"range empty interface", "{{range .Empty3}}-{{.}}-{{else}}EMPTY{{end}}", "-7--8-", tVal, true}, 527 {"range empty nil", "{{range .Empty0}}-{{.}}-{{end}}", "", tVal, true}, 528 {"range $x SI", "{{range $x := .SI}}<{{$x}}>{{end}}", "<3><4><5>", tVal, true}, 529 {"range $x $y SI", "{{range $x, $y := .SI}}<{{$x}}={{$y}}>{{end}}", "<0=3><1=4><2=5>", tVal, true}, 530 {"range $x MSIone", "{{range $x := .MSIone}}<{{$x}}>{{end}}", "<1>", tVal, true}, 531 {"range $x $y MSIone", "{{range $x, $y := .MSIone}}<{{$x}}={{$y}}>{{end}}", "<one=1>", tVal, true}, 532 {"range $x PSI", "{{range $x := .PSI}}<{{$x}}>{{end}}", "<21><22><23>", tVal, true}, 533 {"declare in range", "{{range $x := .PSI}}<{{$foo:=$x}}{{$x}}>{{end}}", "<21><22><23>", tVal, true}, 534 {"range count", `{{range $i, $x := count 5}}[{{$i}}]{{$x}}{{end}}`, "[0]a[1]b[2]c[3]d[4]e", tVal, true}, 535 {"range nil count", `{{range $i, $x := count 0}}{{else}}empty{{end}}`, "empty", tVal, true}, 536 537 // Cute examples. 538 {"or as if true", `{{or .SI "slice is empty"}}`, "[3 4 5]", tVal, true}, 539 {"or as if false", `{{or .SIEmpty "slice is empty"}}`, "slice is empty", tVal, true}, 540 541 // Error handling. 542 {"error method, error", "{{.MyError true}}", "", tVal, false}, 543 {"error method, no error", "{{.MyError false}}", "false", tVal, true}, 544 545 // Fixed bugs. 546 // Must separate dot and receiver; otherwise args are evaluated with dot set to variable. 547 {"bug0", "{{range .MSIone}}{{if $.Method1 .}}X{{end}}{{end}}", "X", tVal, true}, 548 // Do not loop endlessly in indirect for non-empty interfaces. 549 // The bug appears with *interface only; looped forever. 550 {"bug1", "{{.Method0}}", "M0", &iVal, true}, 551 // Was taking address of interface field, so method set was empty. 552 {"bug2", "{{$.NonEmptyInterface.Method0}}", "M0", tVal, true}, 553 // Struct values were not legal in with - mere oversight. 554 {"bug3", "{{with $}}{{.Method0}}{{end}}", "M0", tVal, true}, 555 // Nil interface values in if. 556 {"bug4", "{{if .Empty0}}non-nil{{else}}nil{{end}}", "nil", tVal, true}, 557 // Stringer. 558 {"bug5", "{{.Str}}", "foozle", tVal, true}, 559 {"bug5a", "{{.Err}}", "erroozle", tVal, true}, 560 // Args need to be indirected and dereferenced sometimes. 561 {"bug6a", "{{vfunc .V0 .V1}}", "vfunc", tVal, true}, 562 {"bug6b", "{{vfunc .V0 .V0}}", "vfunc", tVal, true}, 563 {"bug6c", "{{vfunc .V1 .V0}}", "vfunc", tVal, true}, 564 {"bug6d", "{{vfunc .V1 .V1}}", "vfunc", tVal, true}, 565 // Legal parse but illegal execution: non-function should have no arguments. 566 {"bug7a", "{{3 2}}", "", tVal, false}, 567 {"bug7b", "{{$x := 1}}{{$x 2}}", "", tVal, false}, 568 {"bug7c", "{{$x := 1}}{{3 | $x}}", "", tVal, false}, 569 // Pipelined arg was not being type-checked. 570 {"bug8a", "{{3|oneArg}}", "", tVal, false}, 571 {"bug8b", "{{4|dddArg 3}}", "", tVal, false}, 572 // A bug was introduced that broke map lookups for lower-case names. 573 {"bug9", "{{.cause}}", "neglect", map[string]string{"cause": "neglect"}, true}, 574 // Field chain starting with function did not work. 575 {"bug10", "{{mapOfThree.three}}-{{(mapOfThree).three}}", "3-3", 0, true}, 576 // Dereferencing nil pointer while evaluating function arguments should not panic. Issue 7333. 577 {"bug11", "{{valueString .PS}}", "", T{}, false}, 578 // 0xef gave constant type float64. Issue 8622. 579 {"bug12xe", "{{printf `%T` 0xef}}", "int", T{}, true}, 580 {"bug12xE", "{{printf `%T` 0xEE}}", "int", T{}, true}, 581 {"bug12Xe", "{{printf `%T` 0Xef}}", "int", T{}, true}, 582 {"bug12XE", "{{printf `%T` 0XEE}}", "int", T{}, true}, 583 // Chained nodes did not work as arguments. Issue 8473. 584 {"bug13", "{{print (.Copy).I}}", "17", tVal, true}, 585 // Didn't protect against nil or literal values in field chains. 586 {"bug14a", "{{(nil).True}}", "", tVal, false}, 587 {"bug14b", "{{$x := nil}}{{$x.anything}}", "", tVal, false}, 588 {"bug14c", `{{$x := (1.0)}}{{$y := ("hello")}}{{$x.anything}}{{$y.true}}`, "", tVal, false}, 589 // Didn't call validateType on function results. Issue 10800. 590 {"bug15", "{{valueString returnInt}}", "", tVal, false}, 591 // Variadic function corner cases. Issue 10946. 592 {"bug16a", "{{true|printf}}", "", tVal, false}, 593 {"bug16b", "{{1|printf}}", "", tVal, false}, 594 {"bug16c", "{{1.1|printf}}", "", tVal, false}, 595 {"bug16d", "{{'x'|printf}}", "", tVal, false}, 596 {"bug16e", "{{0i|printf}}", "", tVal, false}, 597 {"bug16f", "{{true|twoArgs \"xxx\"}}", "", tVal, false}, 598 {"bug16g", "{{\"aaa\" |twoArgs \"bbb\"}}", "twoArgs=bbbaaa", tVal, true}, 599 {"bug16h", "{{1|oneArg}}", "", tVal, false}, 600 {"bug16i", "{{\"aaa\"|oneArg}}", "oneArg=aaa", tVal, true}, 601 {"bug16j", "{{1+2i|printf \"%v\"}}", "(1+2i)", tVal, true}, 602 {"bug16k", "{{\"aaa\"|printf }}", "aaa", tVal, true}, 603 {"bug17a", "{{.NonEmptyInterface.X}}", "x", tVal, true}, 604 {"bug17b", "-{{.NonEmptyInterface.Method1 1234}}-", "-1234-", tVal, true}, 605 {"bug17c", "{{len .NonEmptyInterfacePtS}}", "2", tVal, true}, 606 {"bug17d", "{{index .NonEmptyInterfacePtS 0}}", "a", tVal, true}, 607 {"bug17e", "{{range .NonEmptyInterfacePtS}}-{{.}}-{{end}}", "-a--b-", tVal, true}, 608 } 609 610 func zeroArgs() string { 611 return "zeroArgs" 612 } 613 614 func oneArg(a string) string { 615 return "oneArg=" + a 616 } 617 618 func twoArgs(a, b string) string { 619 return "twoArgs=" + a + b 620 } 621 622 func dddArg(a int, b ...string) string { 623 return fmt.Sprintln(a, b) 624 } 625 626 // count returns a channel that will deliver n sequential 1-letter strings starting at "a" 627 func count(n int) chan string { 628 if n == 0 { 629 return nil 630 } 631 c := make(chan string) 632 go func() { 633 for i := 0; i < n; i++ { 634 c <- "abcdefghijklmnop"[i : i+1] 635 } 636 close(c) 637 }() 638 return c 639 } 640 641 // vfunc takes a *V and a V 642 func vfunc(V, *V) string { 643 return "vfunc" 644 } 645 646 // valueString takes a string, not a pointer. 647 func valueString(v string) string { 648 return "value is ignored" 649 } 650 651 // returnInt returns an int 652 func returnInt() int { 653 return 7 654 } 655 656 func add(args ...int) int { 657 sum := 0 658 for _, x := range args { 659 sum += x 660 } 661 return sum 662 } 663 664 func echo(arg interface{}) interface{} { 665 return arg 666 } 667 668 func makemap(arg ...string) map[string]string { 669 if len(arg)%2 != 0 { 670 panic("bad makemap") 671 } 672 m := make(map[string]string) 673 for i := 0; i < len(arg); i += 2 { 674 m[arg[i]] = arg[i+1] 675 } 676 return m 677 } 678 679 func stringer(s fmt.Stringer) string { 680 return s.String() 681 } 682 683 func mapOfThree() interface{} { 684 return map[string]int{"three": 3} 685 } 686 687 func testExecute(execTests []execTest, template *Template, t *testing.T) { 688 b := new(bytes.Buffer) 689 funcs := FuncMap{ 690 "add": add, 691 "count": count, 692 "dddArg": dddArg, 693 "echo": echo, 694 "makemap": makemap, 695 "mapOfThree": mapOfThree, 696 "oneArg": oneArg, 697 "returnInt": returnInt, 698 "stringer": stringer, 699 "twoArgs": twoArgs, 700 "typeOf": typeOf, 701 "valueString": valueString, 702 "vfunc": vfunc, 703 "zeroArgs": zeroArgs, 704 } 705 for _, test := range execTests { 706 var tmpl *Template 707 var err error 708 if template == nil { 709 tmpl, err = New(test.name).Funcs(funcs).Parse(test.input) 710 } else { 711 tmpl, err = template.New(test.name).Funcs(funcs).Parse(test.input) 712 } 713 if err != nil { 714 t.Errorf("%s: parse error: %s", test.name, err) 715 continue 716 } 717 b.Reset() 718 err = tmpl.Execute(b, test.data) 719 switch { 720 case !test.ok && err == nil: 721 t.Errorf("%s: expected error; got none", test.name) 722 continue 723 case test.ok && err != nil: 724 t.Errorf("%s: unexpected execute error: %s", test.name, err) 725 continue 726 case !test.ok && err != nil: 727 // expected error, got one 728 if *debug { 729 fmt.Printf("%s: %s\n\t%s\n", test.name, test.input, err) 730 } 731 } 732 result := b.String() 733 if result != test.output { 734 t.Errorf("%s: expected\n\t%q\ngot\n\t%q", test.name, test.output, result) 735 } 736 } 737 } 738 739 func TestExecute(t *testing.T) { 740 testExecute(execTests, nil, t) 741 } 742 743 var delimPairs = []string{ 744 "", "", // default 745 "{{", "}}", // same as default 746 "<<", ">>", // distinct 747 "|", "|", // same 748 "(日)", "(本)", // peculiar 749 } 750 751 func TestDelims(t *testing.T) { 752 const hello = "Hello, world" 753 var value = struct{ Str string }{hello} 754 for i := 0; i < len(delimPairs); i += 2 { 755 text := ".Str" 756 left := delimPairs[i+0] 757 trueLeft := left 758 right := delimPairs[i+1] 759 trueRight := right 760 if left == "" { // default case 761 trueLeft = "{{" 762 } 763 if right == "" { // default case 764 trueRight = "}}" 765 } 766 text = trueLeft + text + trueRight 767 // Now add a comment 768 text += trueLeft + "/*comment*/" + trueRight 769 // Now add an action containing a string. 770 text += trueLeft + `"` + trueLeft + `"` + trueRight 771 // At this point text looks like `{{.Str}}{{/*comment*/}}{{"{{"}}`. 772 tmpl, err := New("delims").Delims(left, right).Parse(text) 773 if err != nil { 774 t.Fatalf("delim %q text %q parse err %s", left, text, err) 775 } 776 var b = new(bytes.Buffer) 777 err = tmpl.Execute(b, value) 778 if err != nil { 779 t.Fatalf("delim %q exec err %s", left, err) 780 } 781 if b.String() != hello+trueLeft { 782 t.Errorf("expected %q got %q", hello+trueLeft, b.String()) 783 } 784 } 785 } 786 787 // Check that an error from a method flows back to the top. 788 func TestExecuteError(t *testing.T) { 789 b := new(bytes.Buffer) 790 tmpl := New("error") 791 _, err := tmpl.Parse("{{.MyError true}}") 792 if err != nil { 793 t.Fatalf("parse error: %s", err) 794 } 795 err = tmpl.Execute(b, tVal) 796 if err == nil { 797 t.Errorf("expected error; got none") 798 } else if !strings.Contains(err.Error(), myError.Error()) { 799 if *debug { 800 fmt.Printf("test execute error: %s\n", err) 801 } 802 t.Errorf("expected myError; got %s", err) 803 } 804 } 805 806 const execErrorText = `line 1 807 line 2 808 line 3 809 {{template "one" .}} 810 {{define "one"}}{{template "two" .}}{{end}} 811 {{define "two"}}{{template "three" .}}{{end}} 812 {{define "three"}}{{index "hi" $}}{{end}}` 813 814 // Check that an error from a nested template contains all the relevant information. 815 func TestExecError(t *testing.T) { 816 tmpl, err := New("top").Parse(execErrorText) 817 if err != nil { 818 t.Fatal("parse error:", err) 819 } 820 var b bytes.Buffer 821 err = tmpl.Execute(&b, 5) // 5 is out of range indexing "hi" 822 if err == nil { 823 t.Fatal("expected error") 824 } 825 const want = `template: top:7:20: executing "three" at <index "hi" $>: error calling index: index out of range: 5` 826 got := err.Error() 827 if got != want { 828 t.Errorf("expected\n%q\ngot\n%q", want, got) 829 } 830 } 831 832 func TestJSEscaping(t *testing.T) { 833 testCases := []struct { 834 in, exp string 835 }{ 836 {`a`, `a`}, 837 {`'foo`, `\'foo`}, 838 {`Go "jump" \`, `Go \"jump\" \\`}, 839 {`Yukihiro says "今日は世界"`, `Yukihiro says \"今日は世界\"`}, 840 {"unprintable \uFDFF", `unprintable \uFDFF`}, 841 {`<html>`, `\x3Chtml\x3E`}, 842 } 843 for _, tc := range testCases { 844 s := JSEscapeString(tc.in) 845 if s != tc.exp { 846 t.Errorf("JS escaping [%s] got [%s] want [%s]", tc.in, s, tc.exp) 847 } 848 } 849 } 850 851 // A nice example: walk a binary tree. 852 853 type Tree struct { 854 Val int 855 Left, Right *Tree 856 } 857 858 // Use different delimiters to test Set.Delims. 859 // Also test the trimming of leading and trailing spaces. 860 const treeTemplate = ` 861 (- define "tree" -) 862 [ 863 (- .Val -) 864 (- with .Left -) 865 (template "tree" . -) 866 (- end -) 867 (- with .Right -) 868 (- template "tree" . -) 869 (- end -) 870 ] 871 (- end -) 872 ` 873 874 func TestTree(t *testing.T) { 875 var tree = &Tree{ 876 1, 877 &Tree{ 878 2, &Tree{ 879 3, 880 &Tree{ 881 4, nil, nil, 882 }, 883 nil, 884 }, 885 &Tree{ 886 5, 887 &Tree{ 888 6, nil, nil, 889 }, 890 nil, 891 }, 892 }, 893 &Tree{ 894 7, 895 &Tree{ 896 8, 897 &Tree{ 898 9, nil, nil, 899 }, 900 nil, 901 }, 902 &Tree{ 903 10, 904 &Tree{ 905 11, nil, nil, 906 }, 907 nil, 908 }, 909 }, 910 } 911 tmpl, err := New("root").Delims("(", ")").Parse(treeTemplate) 912 if err != nil { 913 t.Fatal("parse error:", err) 914 } 915 var b bytes.Buffer 916 const expect = "[1[2[3[4]][5[6]]][7[8[9]][10[11]]]]" 917 // First by looking up the template. 918 err = tmpl.Lookup("tree").Execute(&b, tree) 919 if err != nil { 920 t.Fatal("exec error:", err) 921 } 922 result := b.String() 923 if result != expect { 924 t.Errorf("expected %q got %q", expect, result) 925 } 926 // Then direct to execution. 927 b.Reset() 928 err = tmpl.ExecuteTemplate(&b, "tree", tree) 929 if err != nil { 930 t.Fatal("exec error:", err) 931 } 932 result = b.String() 933 if result != expect { 934 t.Errorf("expected %q got %q", expect, result) 935 } 936 } 937 938 func TestExecuteOnNewTemplate(t *testing.T) { 939 // This is issue 3872. 940 New("Name").Templates() 941 // This is issue 11379. 942 new(Template).Templates() 943 new(Template).Parse("") 944 new(Template).New("abc").Parse("") 945 new(Template).Execute(nil, nil) // returns an error (but does not crash) 946 new(Template).ExecuteTemplate(nil, "XXX", nil) // returns an error (but does not crash) 947 } 948 949 const testTemplates = `{{define "one"}}one{{end}}{{define "two"}}two{{end}}` 950 951 func TestMessageForExecuteEmpty(t *testing.T) { 952 // Test a truly empty template. 953 tmpl := New("empty") 954 var b bytes.Buffer 955 err := tmpl.Execute(&b, 0) 956 if err == nil { 957 t.Fatal("expected initial error") 958 } 959 got := err.Error() 960 want := `template: empty: "empty" is an incomplete or empty template` 961 if got != want { 962 t.Errorf("expected error %s got %s", want, got) 963 } 964 // Add a non-empty template to check that the error is helpful. 965 tests, err := New("").Parse(testTemplates) 966 if err != nil { 967 t.Fatal(err) 968 } 969 tmpl.AddParseTree("secondary", tests.Tree) 970 err = tmpl.Execute(&b, 0) 971 if err == nil { 972 t.Fatal("expected second error") 973 } 974 got = err.Error() 975 want = `template: empty: "empty" is an incomplete or empty template` 976 if got != want { 977 t.Errorf("expected error %s got %s", want, got) 978 } 979 // Make sure we can execute the secondary. 980 err = tmpl.ExecuteTemplate(&b, "secondary", 0) 981 if err != nil { 982 t.Fatal(err) 983 } 984 } 985 986 func TestFinalForPrintf(t *testing.T) { 987 tmpl, err := New("").Parse(`{{"x" | printf}}`) 988 if err != nil { 989 t.Fatal(err) 990 } 991 var b bytes.Buffer 992 err = tmpl.Execute(&b, 0) 993 if err != nil { 994 t.Fatal(err) 995 } 996 } 997 998 type cmpTest struct { 999 expr string 1000 truth string 1001 ok bool 1002 } 1003 1004 var cmpTests = []cmpTest{ 1005 {"eq true true", "true", true}, 1006 {"eq true false", "false", true}, 1007 {"eq 1+2i 1+2i", "true", true}, 1008 {"eq 1+2i 1+3i", "false", true}, 1009 {"eq 1.5 1.5", "true", true}, 1010 {"eq 1.5 2.5", "false", true}, 1011 {"eq 1 1", "true", true}, 1012 {"eq 1 2", "false", true}, 1013 {"eq `xy` `xy`", "true", true}, 1014 {"eq `xy` `xyz`", "false", true}, 1015 {"eq .Uthree .Uthree", "true", true}, 1016 {"eq .Uthree .Ufour", "false", true}, 1017 {"eq 3 4 5 6 3", "true", true}, 1018 {"eq 3 4 5 6 7", "false", true}, 1019 {"ne true true", "false", true}, 1020 {"ne true false", "true", true}, 1021 {"ne 1+2i 1+2i", "false", true}, 1022 {"ne 1+2i 1+3i", "true", true}, 1023 {"ne 1.5 1.5", "false", true}, 1024 {"ne 1.5 2.5", "true", true}, 1025 {"ne 1 1", "false", true}, 1026 {"ne 1 2", "true", true}, 1027 {"ne `xy` `xy`", "false", true}, 1028 {"ne `xy` `xyz`", "true", true}, 1029 {"ne .Uthree .Uthree", "false", true}, 1030 {"ne .Uthree .Ufour", "true", true}, 1031 {"lt 1.5 1.5", "false", true}, 1032 {"lt 1.5 2.5", "true", true}, 1033 {"lt 1 1", "false", true}, 1034 {"lt 1 2", "true", true}, 1035 {"lt `xy` `xy`", "false", true}, 1036 {"lt `xy` `xyz`", "true", true}, 1037 {"lt .Uthree .Uthree", "false", true}, 1038 {"lt .Uthree .Ufour", "true", true}, 1039 {"le 1.5 1.5", "true", true}, 1040 {"le 1.5 2.5", "true", true}, 1041 {"le 2.5 1.5", "false", true}, 1042 {"le 1 1", "true", true}, 1043 {"le 1 2", "true", true}, 1044 {"le 2 1", "false", true}, 1045 {"le `xy` `xy`", "true", true}, 1046 {"le `xy` `xyz`", "true", true}, 1047 {"le `xyz` `xy`", "false", true}, 1048 {"le .Uthree .Uthree", "true", true}, 1049 {"le .Uthree .Ufour", "true", true}, 1050 {"le .Ufour .Uthree", "false", true}, 1051 {"gt 1.5 1.5", "false", true}, 1052 {"gt 1.5 2.5", "false", true}, 1053 {"gt 1 1", "false", true}, 1054 {"gt 2 1", "true", true}, 1055 {"gt 1 2", "false", true}, 1056 {"gt `xy` `xy`", "false", true}, 1057 {"gt `xy` `xyz`", "false", true}, 1058 {"gt .Uthree .Uthree", "false", true}, 1059 {"gt .Uthree .Ufour", "false", true}, 1060 {"gt .Ufour .Uthree", "true", true}, 1061 {"ge 1.5 1.5", "true", true}, 1062 {"ge 1.5 2.5", "false", true}, 1063 {"ge 2.5 1.5", "true", true}, 1064 {"ge 1 1", "true", true}, 1065 {"ge 1 2", "false", true}, 1066 {"ge 2 1", "true", true}, 1067 {"ge `xy` `xy`", "true", true}, 1068 {"ge `xy` `xyz`", "false", true}, 1069 {"ge `xyz` `xy`", "true", true}, 1070 {"ge .Uthree .Uthree", "true", true}, 1071 {"ge .Uthree .Ufour", "false", true}, 1072 {"ge .Ufour .Uthree", "true", true}, 1073 // Mixing signed and unsigned integers. 1074 {"eq .Uthree .Three", "true", true}, 1075 {"eq .Three .Uthree", "true", true}, 1076 {"le .Uthree .Three", "true", true}, 1077 {"le .Three .Uthree", "true", true}, 1078 {"ge .Uthree .Three", "true", true}, 1079 {"ge .Three .Uthree", "true", true}, 1080 {"lt .Uthree .Three", "false", true}, 1081 {"lt .Three .Uthree", "false", true}, 1082 {"gt .Uthree .Three", "false", true}, 1083 {"gt .Three .Uthree", "false", true}, 1084 {"eq .Ufour .Three", "false", true}, 1085 {"lt .Ufour .Three", "false", true}, 1086 {"gt .Ufour .Three", "true", true}, 1087 {"eq .NegOne .Uthree", "false", true}, 1088 {"eq .Uthree .NegOne", "false", true}, 1089 {"ne .NegOne .Uthree", "true", true}, 1090 {"ne .Uthree .NegOne", "true", true}, 1091 {"lt .NegOne .Uthree", "true", true}, 1092 {"lt .Uthree .NegOne", "false", true}, 1093 {"le .NegOne .Uthree", "true", true}, 1094 {"le .Uthree .NegOne", "false", true}, 1095 {"gt .NegOne .Uthree", "false", true}, 1096 {"gt .Uthree .NegOne", "true", true}, 1097 {"ge .NegOne .Uthree", "false", true}, 1098 {"ge .Uthree .NegOne", "true", true}, 1099 {"eq (index `x` 0) 'x'", "true", true}, // The example that triggered this rule. 1100 {"eq (index `x` 0) 'y'", "false", true}, 1101 // Errors 1102 {"eq `xy` 1", "", false}, // Different types. 1103 {"eq 2 2.0", "", false}, // Different types. 1104 {"lt true true", "", false}, // Unordered types. 1105 {"lt 1+0i 1+0i", "", false}, // Unordered types. 1106 } 1107 1108 func TestComparison(t *testing.T) { 1109 b := new(bytes.Buffer) 1110 var cmpStruct = struct { 1111 Uthree, Ufour uint 1112 NegOne, Three int 1113 }{3, 4, -1, 3} 1114 for _, test := range cmpTests { 1115 text := fmt.Sprintf("{{if %s}}true{{else}}false{{end}}", test.expr) 1116 tmpl, err := New("empty").Parse(text) 1117 if err != nil { 1118 t.Fatalf("%q: %s", test.expr, err) 1119 } 1120 b.Reset() 1121 err = tmpl.Execute(b, &cmpStruct) 1122 if test.ok && err != nil { 1123 t.Errorf("%s errored incorrectly: %s", test.expr, err) 1124 continue 1125 } 1126 if !test.ok && err == nil { 1127 t.Errorf("%s did not error", test.expr) 1128 continue 1129 } 1130 if b.String() != test.truth { 1131 t.Errorf("%s: want %s; got %s", test.expr, test.truth, b.String()) 1132 } 1133 } 1134 } 1135 1136 func TestMissingMapKey(t *testing.T) { 1137 data := map[string]int{ 1138 "x": 99, 1139 } 1140 tmpl, err := New("t1").Parse("{{.x}} {{.y}}") 1141 if err != nil { 1142 t.Fatal(err) 1143 } 1144 var b bytes.Buffer 1145 // By default, just get "<no value>" 1146 err = tmpl.Execute(&b, data) 1147 if err != nil { 1148 t.Fatal(err) 1149 } 1150 want := "99 <no value>" 1151 got := b.String() 1152 if got != want { 1153 t.Errorf("got %q; expected %q", got, want) 1154 } 1155 // Same if we set the option explicitly to the default. 1156 tmpl.Option("missingkey=default") 1157 b.Reset() 1158 err = tmpl.Execute(&b, data) 1159 if err != nil { 1160 t.Fatal("default:", err) 1161 } 1162 want = "99 <no value>" 1163 got = b.String() 1164 if got != want { 1165 t.Errorf("got %q; expected %q", got, want) 1166 } 1167 // Next we ask for a zero value 1168 tmpl.Option("missingkey=zero") 1169 b.Reset() 1170 err = tmpl.Execute(&b, data) 1171 if err != nil { 1172 t.Fatal("zero:", err) 1173 } 1174 want = "99 0" 1175 got = b.String() 1176 if got != want { 1177 t.Errorf("got %q; expected %q", got, want) 1178 } 1179 // Now we ask for an error. 1180 tmpl.Option("missingkey=error") 1181 err = tmpl.Execute(&b, data) 1182 if err == nil { 1183 t.Errorf("expected error; got none") 1184 } 1185 // same Option, but now a nil interface: ask for an error 1186 err = tmpl.Execute(&b, nil) 1187 t.Log(err) 1188 if err == nil { 1189 t.Errorf("expected error for nil-interface; got none") 1190 } 1191 } 1192 1193 // Test that the error message for multiline unterminated string 1194 // refers to the line number of the opening quote. 1195 func TestUnterminatedStringError(t *testing.T) { 1196 _, err := New("X").Parse("hello\n\n{{`unterminated\n\n\n\n}}\n some more\n\n") 1197 if err == nil { 1198 t.Fatal("expected error") 1199 } 1200 str := err.Error() 1201 if !strings.Contains(str, "X:3: unexpected unterminated raw quoted string") { 1202 t.Fatalf("unexpected error: %s", str) 1203 } 1204 } 1205 1206 const alwaysErrorText = "always be failing" 1207 1208 var alwaysError = errors.New(alwaysErrorText) 1209 1210 type ErrorWriter int 1211 1212 func (e ErrorWriter) Write(p []byte) (int, error) { 1213 return 0, alwaysError 1214 } 1215 1216 func TestExecuteGivesExecError(t *testing.T) { 1217 // First, a non-execution error shouldn't be an ExecError. 1218 tmpl, err := New("X").Parse("hello") 1219 if err != nil { 1220 t.Fatal(err) 1221 } 1222 err = tmpl.Execute(ErrorWriter(0), 0) 1223 if err == nil { 1224 t.Fatal("expected error; got none") 1225 } 1226 if err.Error() != alwaysErrorText { 1227 t.Errorf("expected %q error; got %q", alwaysErrorText, err) 1228 } 1229 // This one should be an ExecError. 1230 tmpl, err = New("X").Parse("hello, {{.X.Y}}") 1231 if err != nil { 1232 t.Fatal(err) 1233 } 1234 err = tmpl.Execute(ioutil.Discard, 0) 1235 if err == nil { 1236 t.Fatal("expected error; got none") 1237 } 1238 eerr, ok := err.(ExecError) 1239 if !ok { 1240 t.Fatalf("did not expect ExecError %s", eerr) 1241 } 1242 expect := "field X in type int" 1243 if !strings.Contains(err.Error(), expect) { 1244 t.Errorf("expected %q; got %q", expect, err) 1245 } 1246 } 1247 1248 func funcNameTestFunc() int { 1249 return 0 1250 } 1251 1252 func TestGoodFuncNames(t *testing.T) { 1253 names := []string{ 1254 "_", 1255 "a", 1256 "a1", 1257 "a1", 1258 "Ӵ", 1259 } 1260 for _, name := range names { 1261 tmpl := New("X").Funcs( 1262 FuncMap{ 1263 name: funcNameTestFunc, 1264 }, 1265 ) 1266 if tmpl == nil { 1267 t.Fatalf("nil result for %q", name) 1268 } 1269 } 1270 } 1271 1272 func TestBadFuncNames(t *testing.T) { 1273 names := []string{ 1274 "", 1275 "2", 1276 "a-b", 1277 } 1278 for _, name := range names { 1279 testBadFuncName(name, t) 1280 } 1281 } 1282 1283 func testBadFuncName(name string, t *testing.T) { 1284 t.Helper() 1285 defer func() { 1286 recover() 1287 }() 1288 New("X").Funcs( 1289 FuncMap{ 1290 name: funcNameTestFunc, 1291 }, 1292 ) 1293 // If we get here, the name did not cause a panic, which is how Funcs 1294 // reports an error. 1295 t.Errorf("%q succeeded incorrectly as function name", name) 1296 } 1297 1298 func TestBlock(t *testing.T) { 1299 const ( 1300 input = `a({{block "inner" .}}bar({{.}})baz{{end}})b` 1301 want = `a(bar(hello)baz)b` 1302 overlay = `{{define "inner"}}foo({{.}})bar{{end}}` 1303 want2 = `a(foo(goodbye)bar)b` 1304 ) 1305 tmpl, err := New("outer").Parse(input) 1306 if err != nil { 1307 t.Fatal(err) 1308 } 1309 tmpl2, err := Must(tmpl.Clone()).Parse(overlay) 1310 if err != nil { 1311 t.Fatal(err) 1312 } 1313 1314 var buf bytes.Buffer 1315 if err := tmpl.Execute(&buf, "hello"); err != nil { 1316 t.Fatal(err) 1317 } 1318 if got := buf.String(); got != want { 1319 t.Errorf("got %q, want %q", got, want) 1320 } 1321 1322 buf.Reset() 1323 if err := tmpl2.Execute(&buf, "goodbye"); err != nil { 1324 t.Fatal(err) 1325 } 1326 if got := buf.String(); got != want2 { 1327 t.Errorf("got %q, want %q", got, want2) 1328 } 1329 } 1330 1331 // Check that calling an invalid field on nil pointer prints 1332 // a field error instead of a distracting nil pointer error. 1333 // https://golang.org/issue/15125 1334 func TestMissingFieldOnNil(t *testing.T) { 1335 tmpl := Must(New("tmpl").Parse("{{.MissingField}}")) 1336 var d *T 1337 err := tmpl.Execute(ioutil.Discard, d) 1338 got := "<nil>" 1339 if err != nil { 1340 got = err.Error() 1341 } 1342 want := "can't evaluate field MissingField in type *template.T" 1343 if !strings.HasSuffix(got, want) { 1344 t.Errorf("got error %q, want %q", got, want) 1345 } 1346 } 1347 1348 func TestMaxExecDepth(t *testing.T) { 1349 tmpl := Must(New("tmpl").Parse(`{{template "tmpl" .}}`)) 1350 err := tmpl.Execute(ioutil.Discard, nil) 1351 got := "<nil>" 1352 if err != nil { 1353 got = err.Error() 1354 } 1355 const want = "exceeded maximum template depth" 1356 if !strings.Contains(got, want) { 1357 t.Errorf("got error %q; want %q", got, want) 1358 } 1359 } 1360 1361 func TestAddrOfIndex(t *testing.T) { 1362 // golang.org/issue/14916. 1363 // Before index worked on reflect.Values, the .String could not be 1364 // found on the (incorrectly unaddressable) V value, 1365 // in contrast to range, which worked fine. 1366 // Also testing that passing a reflect.Value to tmpl.Execute works. 1367 texts := []string{ 1368 `{{range .}}{{.String}}{{end}}`, 1369 `{{with index . 0}}{{.String}}{{end}}`, 1370 } 1371 for _, text := range texts { 1372 tmpl := Must(New("tmpl").Parse(text)) 1373 var buf bytes.Buffer 1374 err := tmpl.Execute(&buf, reflect.ValueOf([]V{{1}})) 1375 if err != nil { 1376 t.Fatalf("%s: Execute: %v", text, err) 1377 } 1378 if buf.String() != "<1>" { 1379 t.Fatalf("%s: template output = %q, want %q", text, &buf, "<1>") 1380 } 1381 } 1382 } 1383 1384 func TestInterfaceValues(t *testing.T) { 1385 // golang.org/issue/17714. 1386 // Before index worked on reflect.Values, interface values 1387 // were always implicitly promoted to the underlying value, 1388 // except that nil interfaces were promoted to the zero reflect.Value. 1389 // Eliminating a round trip to interface{} and back to reflect.Value 1390 // eliminated this promotion, breaking these cases. 1391 tests := []struct { 1392 text string 1393 out string 1394 }{ 1395 {`{{index .Nil 1}}`, "ERROR: index of untyped nil"}, 1396 {`{{index .Slice 2}}`, "2"}, 1397 {`{{index .Slice .Two}}`, "2"}, 1398 {`{{call .Nil 1}}`, "ERROR: call of nil"}, 1399 {`{{call .PlusOne 1}}`, "2"}, 1400 {`{{call .PlusOne .One}}`, "2"}, 1401 {`{{and (index .Slice 0) true}}`, "0"}, 1402 {`{{and .Zero true}}`, "0"}, 1403 {`{{and (index .Slice 1) false}}`, "false"}, 1404 {`{{and .One false}}`, "false"}, 1405 {`{{or (index .Slice 0) false}}`, "false"}, 1406 {`{{or .Zero false}}`, "false"}, 1407 {`{{or (index .Slice 1) true}}`, "1"}, 1408 {`{{or .One true}}`, "1"}, 1409 {`{{not (index .Slice 0)}}`, "true"}, 1410 {`{{not .Zero}}`, "true"}, 1411 {`{{not (index .Slice 1)}}`, "false"}, 1412 {`{{not .One}}`, "false"}, 1413 {`{{eq (index .Slice 0) .Zero}}`, "true"}, 1414 {`{{eq (index .Slice 1) .One}}`, "true"}, 1415 {`{{ne (index .Slice 0) .Zero}}`, "false"}, 1416 {`{{ne (index .Slice 1) .One}}`, "false"}, 1417 {`{{ge (index .Slice 0) .One}}`, "false"}, 1418 {`{{ge (index .Slice 1) .Zero}}`, "true"}, 1419 {`{{gt (index .Slice 0) .One}}`, "false"}, 1420 {`{{gt (index .Slice 1) .Zero}}`, "true"}, 1421 {`{{le (index .Slice 0) .One}}`, "true"}, 1422 {`{{le (index .Slice 1) .Zero}}`, "false"}, 1423 {`{{lt (index .Slice 0) .One}}`, "true"}, 1424 {`{{lt (index .Slice 1) .Zero}}`, "false"}, 1425 } 1426 1427 for _, tt := range tests { 1428 tmpl := Must(New("tmpl").Parse(tt.text)) 1429 var buf bytes.Buffer 1430 err := tmpl.Execute(&buf, map[string]interface{}{ 1431 "PlusOne": func(n int) int { 1432 return n + 1 1433 }, 1434 "Slice": []int{0, 1, 2, 3}, 1435 "One": 1, 1436 "Two": 2, 1437 "Nil": nil, 1438 "Zero": 0, 1439 }) 1440 if strings.HasPrefix(tt.out, "ERROR:") { 1441 e := strings.TrimSpace(strings.TrimPrefix(tt.out, "ERROR:")) 1442 if err == nil || !strings.Contains(err.Error(), e) { 1443 t.Errorf("%s: Execute: %v, want error %q", tt.text, err, e) 1444 } 1445 continue 1446 } 1447 if err != nil { 1448 t.Errorf("%s: Execute: %v", tt.text, err) 1449 continue 1450 } 1451 if buf.String() != tt.out { 1452 t.Errorf("%s: template output = %q, want %q", tt.text, &buf, tt.out) 1453 } 1454 } 1455 } 1456 1457 // Check that panics during calls are recovered and returned as errors. 1458 func TestExecutePanicDuringCall(t *testing.T) { 1459 funcs := map[string]interface{}{ 1460 "doPanic": func() string { 1461 panic("custom panic string") 1462 }, 1463 } 1464 tests := []struct { 1465 name string 1466 input string 1467 data interface{} 1468 wantErr string 1469 }{ 1470 { 1471 "direct func call panics", 1472 "{{doPanic}}", (*T)(nil), 1473 `template: t:1:2: executing "t" at <doPanic>: error calling doPanic: custom panic string`, 1474 }, 1475 { 1476 "indirect func call panics", 1477 "{{call doPanic}}", (*T)(nil), 1478 `template: t:1:7: executing "t" at <doPanic>: error calling doPanic: custom panic string`, 1479 }, 1480 { 1481 "direct method call panics", 1482 "{{.GetU}}", (*T)(nil), 1483 `template: t:1:2: executing "t" at <.GetU>: error calling GetU: runtime error: invalid memory address or nil pointer dereference`, 1484 }, 1485 { 1486 "indirect method call panics", 1487 "{{call .GetU}}", (*T)(nil), 1488 `template: t:1:7: executing "t" at <.GetU>: error calling GetU: runtime error: invalid memory address or nil pointer dereference`, 1489 }, 1490 { 1491 "func field call panics", 1492 "{{call .PanicFunc}}", tVal, 1493 `template: t:1:2: executing "t" at <call .PanicFunc>: error calling call: test panic`, 1494 }, 1495 } 1496 for _, tc := range tests { 1497 b := new(bytes.Buffer) 1498 tmpl, err := New("t").Funcs(funcs).Parse(tc.input) 1499 if err != nil { 1500 t.Fatalf("parse error: %s", err) 1501 } 1502 err = tmpl.Execute(b, tc.data) 1503 if err == nil { 1504 t.Errorf("%s: expected error; got none", tc.name) 1505 } else if !strings.Contains(err.Error(), tc.wantErr) { 1506 if *debug { 1507 fmt.Printf("%s: test execute error: %s\n", tc.name, err) 1508 } 1509 t.Errorf("%s: expected error:\n%s\ngot:\n%s", tc.name, tc.wantErr, err) 1510 } 1511 } 1512 }