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