summaryrefslogtreecommitdiff
path: root/internal/texttemplate/exec_test.go
blob: 4696b3c4c07729ab07c98d7f515e50c52338d41c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// Taken and adapted from the stdlib text/template/exec_test.go.
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package texttemplate

import (
	"bytes"
	"testing"
	gotemplate "text/template"
)

// T has lots of interesting pieces to use to test execution.
type T struct {
	Tmpl   *gotemplate.Template
	Empty3 any
	S      string
	SI     []int
	SICap  []int
	AI     [3]int
}

var tVal = &T{
	S:      "xyz",
	SI:     []int{3, 4, 5},
	SICap:  make([]int, 5, 10),
	AI:     [3]int{3, 4, 5},
	Empty3: []int{7, 8},
	Tmpl:   gotemplate.Must(gotemplate.New("").Parse("test template")),
}

//nolint:govet
type execTest struct {
	name   string
	input  string
	output string
	data   any
	ok     bool
}

var execTests = []execTest{
	// Slicing.
	{"slice[:]", "{{slice .SI}}", "[3 4 5]", tVal, true},
	{"slice[1:]", "{{slice .SI 1}}", "[4 5]", tVal, true},
	{"slice[1:2]", "{{slice .SI 1 2}}", "[4]", tVal, true},
	{"slice[-1:]", "{{slice .SI -1}}", "", tVal, false},
	{"slice[1:-2]", "{{slice .SI 1 -2}}", "", tVal, false},
	{"slice[1:2:-1]", "{{slice .SI 1 2 -1}}", "", tVal, false},
	{"slice[2:1]", "{{slice .SI 2 1}}", "", tVal, false},
	{"slice[2:2:1]", "{{slice .SI 2 2 1}}", "", tVal, false},
	{"out of range", "{{slice .SI 4 5}}", "", tVal, false},
	{"out of range", "{{slice .SI 2 2 5}}", "", tVal, false},
	{"len(s) < indexes < cap(s)", "{{slice .SICap 6 10}}", "[0 0 0 0]", tVal, true},
	{"len(s) < indexes < cap(s)", "{{slice .SICap 6 10 10}}", "[0 0 0 0]", tVal, true},
	{"indexes > cap(s)", "{{slice .SICap 10 11}}", "", tVal, false},
	{"indexes > cap(s)", "{{slice .SICap 6 10 11}}", "", tVal, false},
	{"array[:]", "{{slice .AI}}", "[3 4 5]", tVal, true},
	{"array[1:]", "{{slice .AI 1}}", "[4 5]", tVal, true},
	{"array[1:2]", "{{slice .AI 1 2}}", "[4]", tVal, true},
	{"string[:]", "{{slice .S}}", "xyz", tVal, true},
	{"string[0:1]", "{{slice .S 0 1}}", "x", tVal, true},
	{"string[1:]", "{{slice .S 1}}", "yz", tVal, true},
	{"string[1:2]", "{{slice .S 1 2}}", "y", tVal, true},
	{"out of range", "{{slice .S 1 5}}", "", tVal, false},
	{"3-index slice of string", "{{slice .S 1 2 2}}", "", tVal, false},
	{"slice of an interface field", "{{slice .Empty3 0 1}}", "[7]", tVal, true},
}

func testExecute(execTests []execTest, template *gotemplate.Template, t *testing.T) {
	b := new(bytes.Buffer)
	funcs := gotemplate.FuncMap{"slice": GoSlice}

	for _, test := range execTests {
		var tmpl *gotemplate.Template
		var err error
		if template == nil {
			tmpl, err = gotemplate.New(test.name).Funcs(funcs).Parse(test.input)
		} else {
			tmpl, err = template.New(test.name).Funcs(funcs).Parse(test.input)
		}
		if err != nil {
			t.Errorf("%s: parse error: %s", test.name, err)
			continue
		}
		b.Reset()
		err = tmpl.Execute(b, test.data)
		switch {
		case !test.ok && err == nil:
			t.Errorf("%s: expected error; got none", test.name)
			continue
		case test.ok && err != nil:
			t.Errorf("%s: unexpected execute error: %s", test.name, err)
			continue
		case !test.ok && err != nil:
			// expected error, got one
		}
		result := b.String()
		if result != test.output {
			t.Errorf("%s: expected\n\t%q\ngot\n\t%q", test.name, test.output, result)
		}
	}
}

func TestExecute(t *testing.T) {
	testExecute(execTests, nil, t)
}