~ubuntu-branches/ubuntu/trusty/golang/trusty

« back to all changes in this revision

Viewing changes to src/pkg/text/template/parse/lex_test.go

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-08-20 14:06:23 UTC
  • mfrom: (14.1.23 saucy-proposed)
  • Revision ID: package-import@ubuntu.com-20130820140623-b414jfxi3m0qkmrq
Tags: 2:1.1.2-2ubuntu1
* Merge from Debian unstable (LP: #1211749, #1202027). Remaining changes:
  - 016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.
  - d/control,control.cross: Update Breaks/Replaces for Ubuntu
    versions to ensure smooth upgrades, regenerate control file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
package parse
6
6
 
7
7
import (
8
 
        "reflect"
 
8
        "fmt"
9
9
        "testing"
10
10
)
11
11
 
 
12
// Make the types prettyprint.
 
13
var itemName = map[itemType]string{
 
14
        itemError:        "error",
 
15
        itemBool:         "bool",
 
16
        itemChar:         "char",
 
17
        itemCharConstant: "charconst",
 
18
        itemComplex:      "complex",
 
19
        itemColonEquals:  ":=",
 
20
        itemEOF:          "EOF",
 
21
        itemField:        "field",
 
22
        itemIdentifier:   "identifier",
 
23
        itemLeftDelim:    "left delim",
 
24
        itemLeftParen:    "(",
 
25
        itemNumber:       "number",
 
26
        itemPipe:         "pipe",
 
27
        itemRawString:    "raw string",
 
28
        itemRightDelim:   "right delim",
 
29
        itemRightParen:   ")",
 
30
        itemSpace:        "space",
 
31
        itemString:       "string",
 
32
        itemVariable:     "variable",
 
33
 
 
34
        // keywords
 
35
        itemDot:      ".",
 
36
        itemDefine:   "define",
 
37
        itemElse:     "else",
 
38
        itemIf:       "if",
 
39
        itemEnd:      "end",
 
40
        itemNil:      "nil",
 
41
        itemRange:    "range",
 
42
        itemTemplate: "template",
 
43
        itemWith:     "with",
 
44
}
 
45
 
 
46
func (i itemType) String() string {
 
47
        s := itemName[i]
 
48
        if s == "" {
 
49
                return fmt.Sprintf("item%d", int(i))
 
50
        }
 
51
        return s
 
52
}
 
53
 
12
54
type lexTest struct {
13
55
        name  string
14
56
        input string
16
58
}
17
59
 
18
60
var (
19
 
        tEOF      = item{itemEOF, ""}
20
 
        tLeft     = item{itemLeftDelim, "{{"}
21
 
        tRight    = item{itemRightDelim, "}}"}
22
 
        tRange    = item{itemRange, "range"}
23
 
        tPipe     = item{itemPipe, "|"}
24
 
        tFor      = item{itemIdentifier, "for"}
25
 
        tQuote    = item{itemString, `"abc \n\t\" "`}
 
61
        tEOF      = item{itemEOF, 0, ""}
 
62
        tFor      = item{itemIdentifier, 0, "for"}
 
63
        tLeft     = item{itemLeftDelim, 0, "{{"}
 
64
        tLpar     = item{itemLeftParen, 0, "("}
 
65
        tPipe     = item{itemPipe, 0, "|"}
 
66
        tQuote    = item{itemString, 0, `"abc \n\t\" "`}
 
67
        tRange    = item{itemRange, 0, "range"}
 
68
        tRight    = item{itemRightDelim, 0, "}}"}
 
69
        tRpar     = item{itemRightParen, 0, ")"}
 
70
        tSpace    = item{itemSpace, 0, " "}
26
71
        raw       = "`" + `abc\n\t\" ` + "`"
27
 
        tRawQuote = item{itemRawString, raw}
 
72
        tRawQuote = item{itemRawString, 0, raw}
28
73
)
29
74
 
30
75
var lexTests = []lexTest{
31
76
        {"empty", "", []item{tEOF}},
32
 
        {"spaces", " \t\n", []item{{itemText, " \t\n"}, tEOF}},
33
 
        {"text", `now is the time`, []item{{itemText, "now is the time"}, tEOF}},
 
77
        {"spaces", " \t\n", []item{{itemText, 0, " \t\n"}, tEOF}},
 
78
        {"text", `now is the time`, []item{{itemText, 0, "now is the time"}, tEOF}},
34
79
        {"text with comment", "hello-{{/* this is a comment */}}-world", []item{
35
 
                {itemText, "hello-"},
36
 
                {itemText, "-world"},
37
 
                tEOF,
38
 
        }},
39
 
        {"punctuation", "{{,@%}}", []item{
40
 
                tLeft,
41
 
                {itemChar, ","},
42
 
                {itemChar, "@"},
43
 
                {itemChar, "%"},
 
80
                {itemText, 0, "hello-"},
 
81
                {itemText, 0, "-world"},
 
82
                tEOF,
 
83
        }},
 
84
        {"punctuation", "{{,@% }}", []item{
 
85
                tLeft,
 
86
                {itemChar, 0, ","},
 
87
                {itemChar, 0, "@"},
 
88
                {itemChar, 0, "%"},
 
89
                tSpace,
 
90
                tRight,
 
91
                tEOF,
 
92
        }},
 
93
        {"parens", "{{((3))}}", []item{
 
94
                tLeft,
 
95
                tLpar,
 
96
                tLpar,
 
97
                {itemNumber, 0, "3"},
 
98
                tRpar,
 
99
                tRpar,
44
100
                tRight,
45
101
                tEOF,
46
102
        }},
47
103
        {"empty action", `{{}}`, []item{tLeft, tRight, tEOF}},
48
 
        {"for", `{{for }}`, []item{tLeft, tFor, tRight, tEOF}},
 
104
        {"for", `{{for}}`, []item{tLeft, tFor, tRight, tEOF}},
49
105
        {"quote", `{{"abc \n\t\" "}}`, []item{tLeft, tQuote, tRight, tEOF}},
50
106
        {"raw quote", "{{" + raw + "}}", []item{tLeft, tRawQuote, tRight, tEOF}},
51
107
        {"numbers", "{{1 02 0x14 -7.2i 1e3 +1.2e-4 4.2i 1+2i}}", []item{
52
108
                tLeft,
53
 
                {itemNumber, "1"},
54
 
                {itemNumber, "02"},
55
 
                {itemNumber, "0x14"},
56
 
                {itemNumber, "-7.2i"},
57
 
                {itemNumber, "1e3"},
58
 
                {itemNumber, "+1.2e-4"},
59
 
                {itemNumber, "4.2i"},
60
 
                {itemComplex, "1+2i"},
 
109
                {itemNumber, 0, "1"},
 
110
                tSpace,
 
111
                {itemNumber, 0, "02"},
 
112
                tSpace,
 
113
                {itemNumber, 0, "0x14"},
 
114
                tSpace,
 
115
                {itemNumber, 0, "-7.2i"},
 
116
                tSpace,
 
117
                {itemNumber, 0, "1e3"},
 
118
                tSpace,
 
119
                {itemNumber, 0, "+1.2e-4"},
 
120
                tSpace,
 
121
                {itemNumber, 0, "4.2i"},
 
122
                tSpace,
 
123
                {itemComplex, 0, "1+2i"},
61
124
                tRight,
62
125
                tEOF,
63
126
        }},
64
127
        {"characters", `{{'a' '\n' '\'' '\\' '\u00FF' '\xFF' '本'}}`, []item{
65
128
                tLeft,
66
 
                {itemCharConstant, `'a'`},
67
 
                {itemCharConstant, `'\n'`},
68
 
                {itemCharConstant, `'\''`},
69
 
                {itemCharConstant, `'\\'`},
70
 
                {itemCharConstant, `'\u00FF'`},
71
 
                {itemCharConstant, `'\xFF'`},
72
 
                {itemCharConstant, `'本'`},
 
129
                {itemCharConstant, 0, `'a'`},
 
130
                tSpace,
 
131
                {itemCharConstant, 0, `'\n'`},
 
132
                tSpace,
 
133
                {itemCharConstant, 0, `'\''`},
 
134
                tSpace,
 
135
                {itemCharConstant, 0, `'\\'`},
 
136
                tSpace,
 
137
                {itemCharConstant, 0, `'\u00FF'`},
 
138
                tSpace,
 
139
                {itemCharConstant, 0, `'\xFF'`},
 
140
                tSpace,
 
141
                {itemCharConstant, 0, `'本'`},
73
142
                tRight,
74
143
                tEOF,
75
144
        }},
76
145
        {"bools", "{{true false}}", []item{
77
146
                tLeft,
78
 
                {itemBool, "true"},
79
 
                {itemBool, "false"},
 
147
                {itemBool, 0, "true"},
 
148
                tSpace,
 
149
                {itemBool, 0, "false"},
80
150
                tRight,
81
151
                tEOF,
82
152
        }},
83
153
        {"dot", "{{.}}", []item{
84
154
                tLeft,
85
 
                {itemDot, "."},
86
 
                tRight,
87
 
                tEOF,
88
 
        }},
89
 
        {"dots", "{{.x . .2 .x.y}}", []item{
90
 
                tLeft,
91
 
                {itemField, ".x"},
92
 
                {itemDot, "."},
93
 
                {itemNumber, ".2"},
94
 
                {itemField, ".x.y"},
 
155
                {itemDot, 0, "."},
 
156
                tRight,
 
157
                tEOF,
 
158
        }},
 
159
        {"nil", "{{nil}}", []item{
 
160
                tLeft,
 
161
                {itemNil, 0, "nil"},
 
162
                tRight,
 
163
                tEOF,
 
164
        }},
 
165
        {"dots", "{{.x . .2 .x.y.z}}", []item{
 
166
                tLeft,
 
167
                {itemField, 0, ".x"},
 
168
                tSpace,
 
169
                {itemDot, 0, "."},
 
170
                tSpace,
 
171
                {itemNumber, 0, ".2"},
 
172
                tSpace,
 
173
                {itemField, 0, ".x"},
 
174
                {itemField, 0, ".y"},
 
175
                {itemField, 0, ".z"},
95
176
                tRight,
96
177
                tEOF,
97
178
        }},
98
179
        {"keywords", "{{range if else end with}}", []item{
99
180
                tLeft,
100
 
                {itemRange, "range"},
101
 
                {itemIf, "if"},
102
 
                {itemElse, "else"},
103
 
                {itemEnd, "end"},
104
 
                {itemWith, "with"},
 
181
                {itemRange, 0, "range"},
 
182
                tSpace,
 
183
                {itemIf, 0, "if"},
 
184
                tSpace,
 
185
                {itemElse, 0, "else"},
 
186
                tSpace,
 
187
                {itemEnd, 0, "end"},
 
188
                tSpace,
 
189
                {itemWith, 0, "with"},
105
190
                tRight,
106
191
                tEOF,
107
192
        }},
108
193
        {"variables", "{{$c := printf $ $hello $23 $ $var.Field .Method}}", []item{
109
194
                tLeft,
110
 
                {itemVariable, "$c"},
111
 
                {itemColonEquals, ":="},
112
 
                {itemIdentifier, "printf"},
113
 
                {itemVariable, "$"},
114
 
                {itemVariable, "$hello"},
115
 
                {itemVariable, "$23"},
116
 
                {itemVariable, "$"},
117
 
                {itemVariable, "$var.Field"},
118
 
                {itemField, ".Method"},
 
195
                {itemVariable, 0, "$c"},
 
196
                tSpace,
 
197
                {itemColonEquals, 0, ":="},
 
198
                tSpace,
 
199
                {itemIdentifier, 0, "printf"},
 
200
                tSpace,
 
201
                {itemVariable, 0, "$"},
 
202
                tSpace,
 
203
                {itemVariable, 0, "$hello"},
 
204
                tSpace,
 
205
                {itemVariable, 0, "$23"},
 
206
                tSpace,
 
207
                {itemVariable, 0, "$"},
 
208
                tSpace,
 
209
                {itemVariable, 0, "$var"},
 
210
                {itemField, 0, ".Field"},
 
211
                tSpace,
 
212
                {itemField, 0, ".Method"},
 
213
                tRight,
 
214
                tEOF,
 
215
        }},
 
216
        {"variable invocation", "{{$x 23}}", []item{
 
217
                tLeft,
 
218
                {itemVariable, 0, "$x"},
 
219
                tSpace,
 
220
                {itemNumber, 0, "23"},
119
221
                tRight,
120
222
                tEOF,
121
223
        }},
122
224
        {"pipeline", `intro {{echo hi 1.2 |noargs|args 1 "hi"}} outro`, []item{
123
 
                {itemText, "intro "},
 
225
                {itemText, 0, "intro "},
124
226
                tLeft,
125
 
                {itemIdentifier, "echo"},
126
 
                {itemIdentifier, "hi"},
127
 
                {itemNumber, "1.2"},
128
 
                tPipe,
129
 
                {itemIdentifier, "noargs"},
130
 
                tPipe,
131
 
                {itemIdentifier, "args"},
132
 
                {itemNumber, "1"},
133
 
                {itemString, `"hi"`},
 
227
                {itemIdentifier, 0, "echo"},
 
228
                tSpace,
 
229
                {itemIdentifier, 0, "hi"},
 
230
                tSpace,
 
231
                {itemNumber, 0, "1.2"},
 
232
                tSpace,
 
233
                tPipe,
 
234
                {itemIdentifier, 0, "noargs"},
 
235
                tPipe,
 
236
                {itemIdentifier, 0, "args"},
 
237
                tSpace,
 
238
                {itemNumber, 0, "1"},
 
239
                tSpace,
 
240
                {itemString, 0, `"hi"`},
134
241
                tRight,
135
 
                {itemText, " outro"},
 
242
                {itemText, 0, " outro"},
136
243
                tEOF,
137
244
        }},
138
245
        {"declaration", "{{$v := 3}}", []item{
139
246
                tLeft,
140
 
                {itemVariable, "$v"},
141
 
                {itemColonEquals, ":="},
142
 
                {itemNumber, "3"},
 
247
                {itemVariable, 0, "$v"},
 
248
                tSpace,
 
249
                {itemColonEquals, 0, ":="},
 
250
                tSpace,
 
251
                {itemNumber, 0, "3"},
143
252
                tRight,
144
253
                tEOF,
145
254
        }},
146
255
        {"2 declarations", "{{$v , $w := 3}}", []item{
147
256
                tLeft,
148
 
                {itemVariable, "$v"},
149
 
                {itemChar, ","},
150
 
                {itemVariable, "$w"},
151
 
                {itemColonEquals, ":="},
152
 
                {itemNumber, "3"},
 
257
                {itemVariable, 0, "$v"},
 
258
                tSpace,
 
259
                {itemChar, 0, ","},
 
260
                tSpace,
 
261
                {itemVariable, 0, "$w"},
 
262
                tSpace,
 
263
                {itemColonEquals, 0, ":="},
 
264
                tSpace,
 
265
                {itemNumber, 0, "3"},
 
266
                tRight,
 
267
                tEOF,
 
268
        }},
 
269
        {"field of parenthesized expression", "{{(.X).Y}}", []item{
 
270
                tLeft,
 
271
                tLpar,
 
272
                {itemField, 0, ".X"},
 
273
                tRpar,
 
274
                {itemField, 0, ".Y"},
153
275
                tRight,
154
276
                tEOF,
155
277
        }},
156
278
        // errors
157
279
        {"badchar", "#{{\x01}}", []item{
158
 
                {itemText, "#"},
 
280
                {itemText, 0, "#"},
159
281
                tLeft,
160
 
                {itemError, "unrecognized character in action: U+0001"},
 
282
                {itemError, 0, "unrecognized character in action: U+0001"},
161
283
        }},
162
284
        {"unclosed action", "{{\n}}", []item{
163
285
                tLeft,
164
 
                {itemError, "unclosed action"},
 
286
                {itemError, 0, "unclosed action"},
165
287
        }},
166
288
        {"EOF in action", "{{range", []item{
167
289
                tLeft,
168
290
                tRange,
169
 
                {itemError, "unclosed action"},
 
291
                {itemError, 0, "unclosed action"},
170
292
        }},
171
293
        {"unclosed quote", "{{\"\n\"}}", []item{
172
294
                tLeft,
173
 
                {itemError, "unterminated quoted string"},
 
295
                {itemError, 0, "unterminated quoted string"},
174
296
        }},
175
297
        {"unclosed raw quote", "{{`xx\n`}}", []item{
176
298
                tLeft,
177
 
                {itemError, "unterminated raw quoted string"},
 
299
                {itemError, 0, "unterminated raw quoted string"},
178
300
        }},
179
301
        {"unclosed char constant", "{{'\n}}", []item{
180
302
                tLeft,
181
 
                {itemError, "unterminated character constant"},
 
303
                {itemError, 0, "unterminated character constant"},
182
304
        }},
183
305
        {"bad number", "{{3k}}", []item{
184
306
                tLeft,
185
 
                {itemError, `bad number syntax: "3k"`},
 
307
                {itemError, 0, `bad number syntax: "3k"`},
 
308
        }},
 
309
        {"unclosed paren", "{{(3}}", []item{
 
310
                tLeft,
 
311
                tLpar,
 
312
                {itemNumber, 0, "3"},
 
313
                {itemError, 0, `unclosed left paren`},
 
314
        }},
 
315
        {"extra right paren", "{{3)}}", []item{
 
316
                tLeft,
 
317
                {itemNumber, 0, "3"},
 
318
                tRpar,
 
319
                {itemError, 0, `unexpected right paren U+0029 ')'`},
186
320
        }},
187
321
 
188
322
        // Fixed bugs
198
332
                tRight,
199
333
                tEOF,
200
334
        }},
 
335
        {"text with bad comment", "hello-{{/*/}}-world", []item{
 
336
                {itemText, 0, "hello-"},
 
337
                {itemError, 0, `unclosed comment`},
 
338
        }},
201
339
}
202
340
 
203
341
// collect gathers the emitted items into a slice.
213
351
        return
214
352
}
215
353
 
 
354
func equal(i1, i2 []item, checkPos bool) bool {
 
355
        if len(i1) != len(i2) {
 
356
                return false
 
357
        }
 
358
        for k := range i1 {
 
359
                if i1[k].typ != i2[k].typ {
 
360
                        return false
 
361
                }
 
362
                if i1[k].val != i2[k].val {
 
363
                        return false
 
364
                }
 
365
                if checkPos && i1[k].pos != i2[k].pos {
 
366
                        return false
 
367
                }
 
368
        }
 
369
        return true
 
370
}
 
371
 
216
372
func TestLex(t *testing.T) {
217
373
        for _, test := range lexTests {
218
374
                items := collect(&test, "", "")
219
 
                if !reflect.DeepEqual(items, test.items) {
220
 
                        t.Errorf("%s: got\n\t%v\nexpected\n\t%v", test.name, items, test.items)
 
375
                if !equal(items, test.items, false) {
 
376
                        t.Errorf("%s: got\n\t%+v\nexpected\n\t%v", test.name, items, test.items)
221
377
                }
222
378
        }
223
379
}
226
382
var lexDelimTests = []lexTest{
227
383
        {"punctuation", "$$,@%{{}}@@", []item{
228
384
                tLeftDelim,
229
 
                {itemChar, ","},
230
 
                {itemChar, "@"},
231
 
                {itemChar, "%"},
232
 
                {itemChar, "{"},
233
 
                {itemChar, "{"},
234
 
                {itemChar, "}"},
235
 
                {itemChar, "}"},
 
385
                {itemChar, 0, ","},
 
386
                {itemChar, 0, "@"},
 
387
                {itemChar, 0, "%"},
 
388
                {itemChar, 0, "{"},
 
389
                {itemChar, 0, "{"},
 
390
                {itemChar, 0, "}"},
 
391
                {itemChar, 0, "}"},
236
392
                tRightDelim,
237
393
                tEOF,
238
394
        }},
239
395
        {"empty action", `$$@@`, []item{tLeftDelim, tRightDelim, tEOF}},
240
 
        {"for", `$$for @@`, []item{tLeftDelim, tFor, tRightDelim, tEOF}},
 
396
        {"for", `$$for@@`, []item{tLeftDelim, tFor, tRightDelim, tEOF}},
241
397
        {"quote", `$$"abc \n\t\" "@@`, []item{tLeftDelim, tQuote, tRightDelim, tEOF}},
242
398
        {"raw quote", "$$" + raw + "@@", []item{tLeftDelim, tRawQuote, tRightDelim, tEOF}},
243
399
}
244
400
 
245
401
var (
246
 
        tLeftDelim  = item{itemLeftDelim, "$$"}
247
 
        tRightDelim = item{itemRightDelim, "@@"}
 
402
        tLeftDelim  = item{itemLeftDelim, 0, "$$"}
 
403
        tRightDelim = item{itemRightDelim, 0, "@@"}
248
404
)
249
405
 
250
406
func TestDelims(t *testing.T) {
251
407
        for _, test := range lexDelimTests {
252
408
                items := collect(&test, "$$", "@@")
253
 
                if !reflect.DeepEqual(items, test.items) {
254
 
                        t.Errorf("%s: got\n\t%v\nexpected\n\t%v", test.name, items, test.items)
 
409
                if !equal(items, test.items, false) {
 
410
                        t.Errorf("%s: got\n\t%v\nexpected\n\t%v", test.name, items, test.items)
 
411
                }
 
412
        }
 
413
}
 
414
 
 
415
var lexPosTests = []lexTest{
 
416
        {"empty", "", []item{tEOF}},
 
417
        {"punctuation", "{{,@%#}}", []item{
 
418
                {itemLeftDelim, 0, "{{"},
 
419
                {itemChar, 2, ","},
 
420
                {itemChar, 3, "@"},
 
421
                {itemChar, 4, "%"},
 
422
                {itemChar, 5, "#"},
 
423
                {itemRightDelim, 6, "}}"},
 
424
                {itemEOF, 8, ""},
 
425
        }},
 
426
        {"sample", "0123{{hello}}xyz", []item{
 
427
                {itemText, 0, "0123"},
 
428
                {itemLeftDelim, 4, "{{"},
 
429
                {itemIdentifier, 6, "hello"},
 
430
                {itemRightDelim, 11, "}}"},
 
431
                {itemText, 13, "xyz"},
 
432
                {itemEOF, 16, ""},
 
433
        }},
 
434
}
 
435
 
 
436
// The other tests don't check position, to make the test cases easier to construct.
 
437
// This one does.
 
438
func TestPos(t *testing.T) {
 
439
        for _, test := range lexPosTests {
 
440
                items := collect(&test, "", "")
 
441
                if !equal(items, test.items, true) {
 
442
                        t.Errorf("%s: got\n\t%v\nexpected\n\t%v", test.name, items, test.items)
 
443
                        if len(items) == len(test.items) {
 
444
                                // Detailed print; avoid item.String() to expose the position value.
 
445
                                for i := range items {
 
446
                                        if !equal(items[i:i+1], test.items[i:i+1], true) {
 
447
                                                i1 := items[i]
 
448
                                                i2 := test.items[i]
 
449
                                                t.Errorf("\t#%d: got {%v %d %q} expected  {%v %d %q}", i, i1.typ, i1.pos, i1.val, i2.typ, i2.pos, i2.val)
 
450
                                        }
 
451
                                }
 
452
                        }
255
453
                }
256
454
        }
257
455
}