summaryrefslogtreecommitdiff
path: root/src/pkg/exp/template/lex_test.go
blob: 184e833efe2bc85e6db52eb95a7df2badfb81c78 (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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// 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 template

import (
	"reflect"
	"testing"
)

type lexTest struct {
	name  string
	input string
	items []item
}

var (
	tEOF      = item{itemEOF, ""}
	tLeft     = item{itemLeftMeta, "{{"}
	tRight    = item{itemRightMeta, "}}"}
	tRange    = item{itemRange, "range"}
	tPipe     = item{itemPipe, "|"}
	tFor      = item{itemIdentifier, "for"}
	tQuote    = item{itemString, `"abc \n\t\" "`}
	raw       = "`" + `abc\n\t\" ` + "`"
	tRawQuote = item{itemRawString, raw}
)

var lexTests = []lexTest{
	{"empty", "", []item{tEOF}},
	{"spaces", " \t\n", []item{{itemText, " \t\n"}, tEOF}},
	{"text", `now is the time`, []item{{itemText, "now is the time"}, tEOF}},
	{"empty action", `{{}}`, []item{tLeft, tRight, tEOF}},
	{"for", `{{for }}`, []item{tLeft, tFor, tRight, tEOF}},
	{"quote", `{{"abc \n\t\" "}}`, []item{tLeft, tQuote, tRight, tEOF}},
	{"raw quote", "{{" + raw + "}}", []item{tLeft, tRawQuote, tRight, tEOF}},
	{"numbers", "{{1 02 0x14 -7.2i 1e3 +1.2e-4}}", []item{
		tLeft,
		{itemNumber, "1"},
		{itemNumber, "02"},
		{itemNumber, "0x14"},
		{itemNumber, "-7.2i"},
		{itemNumber, "1e3"},
		{itemNumber, "+1.2e-4"},
		tRight,
		tEOF,
	}},
	{"dots", "{{.x . .2 .x.y }}", []item{
		tLeft,
		{itemField, ".x"},
		{itemDot, "."},
		{itemNumber, ".2"},
		{itemField, ".x"},
		{itemField, ".y"},
		tRight,
		tEOF,
	}},
	{"keywords", "{{range if else end}}", []item{
		tLeft,
		{itemRange, "range"},
		{itemIf, "if"},
		{itemElse, "else"},
		{itemEnd, "end"},
		tRight,
		tEOF,
	}},
	{"pipeline", `intro {{echo hi 1.2 |noargs|args 1 "hi"}} outro`, []item{
		{itemText, "intro "},
		tLeft,
		{itemIdentifier, "echo"},
		{itemIdentifier, "hi"},
		{itemNumber, "1.2"},
		tPipe,
		{itemIdentifier, "noargs"},
		tPipe,
		{itemIdentifier, "args"},
		{itemNumber, "1"},
		{itemString, `"hi"`},
		tRight,
		{itemText, " outro"},
		tEOF,
	}},
	// errors
	{"badchar", "#{{#}}", []item{
		{itemText, "#"},
		tLeft,
		{itemError, "unrecognized character in action: U+0023 '#'"},
	}},
	{"unclosed action", "{{\n}}", []item{
		tLeft,
		{itemError, "unclosed action"},
	}},
	{"EOF in action", "{{range", []item{
		tLeft,
		tRange,
		{itemError, "unclosed action"},
	}},
	{"unclosed quote", "{{\"\n\"}}", []item{
		tLeft,
		{itemError, "unterminated quoted string"},
	}},
	{"unclosed raw quote", "{{`xx\n`}}", []item{
		tLeft,
		{itemError, "unterminated raw quoted string"},
	}},
	{"bad number", "{{3k}}", []item{
		tLeft,
		{itemError, `bad number syntax: "3k"`},
	}},
}

// collect gathers the emitted items into a slice.
func collect(t *lexTest) (items []item) {
	_, tokens := lex(t.name, t.input)
	for i := range tokens {
		items = append(items, i)
	}
	return
}

func TestLex(t *testing.T) {
	for _, test := range lexTests {
		items := collect(&test)
		if !reflect.DeepEqual(items, test.items) {
			t.Errorf("%s: got\n\t%v\nexpected\n\t%v", test.name, items, test.items)
		}
	}
}