1
2
3
4
5
6
7
8
9
10 package main
11
12 import (
13 "os"
14 "path/filepath"
15 "strings"
16 "testing"
17
18 "golang.org/x/tools/internal/testenv"
19 )
20
21
22 type Golden struct {
23 name string
24 trimPrefix string
25 lineComment bool
26 input string
27 output string
28 }
29
30 var golden = []Golden{
31 {"day", "", false, day_in, day_out},
32 {"offset", "", false, offset_in, offset_out},
33 {"gap", "", false, gap_in, gap_out},
34 {"num", "", false, num_in, num_out},
35 {"unum", "", false, unum_in, unum_out},
36 {"unumpos", "", false, unumpos_in, unumpos_out},
37 {"prime", "", false, prime_in, prime_out},
38 {"prefix", "Type", false, prefix_in, prefix_out},
39 {"tokens", "", true, tokens_in, tokens_out},
40 }
41
42
43
44
45 const day_in = `type Day int
46 const (
47 Monday Day = iota
48 Tuesday
49 Wednesday
50 Thursday
51 Friday
52 Saturday
53 Sunday
54 )
55 `
56
57 const day_out = `func _() {
58 // An "invalid array index" compiler error signifies that the constant values have changed.
59 // Re-run the stringer command to generate them again.
60 var x [1]struct{}
61 _ = x[Monday-0]
62 _ = x[Tuesday-1]
63 _ = x[Wednesday-2]
64 _ = x[Thursday-3]
65 _ = x[Friday-4]
66 _ = x[Saturday-5]
67 _ = x[Sunday-6]
68 }
69
70 const _Day_name = "MondayTuesdayWednesdayThursdayFridaySaturdaySunday"
71
72 var _Day_index = [...]uint8{0, 6, 13, 22, 30, 36, 44, 50}
73
74 func (i Day) String() string {
75 if i < 0 || i >= Day(len(_Day_index)-1) {
76 return "Day(" + strconv.FormatInt(int64(i), 10) + ")"
77 }
78 return _Day_name[_Day_index[i]:_Day_index[i+1]]
79 }
80 `
81
82
83
84 const offset_in = `type Number int
85 const (
86 _ Number = iota
87 One
88 Two
89 Three
90 AnotherOne = One // Duplicate; note that AnotherOne doesn't appear below.
91 )
92 `
93
94 const offset_out = `func _() {
95 // An "invalid array index" compiler error signifies that the constant values have changed.
96 // Re-run the stringer command to generate them again.
97 var x [1]struct{}
98 _ = x[One-1]
99 _ = x[Two-2]
100 _ = x[Three-3]
101 }
102
103 const _Number_name = "OneTwoThree"
104
105 var _Number_index = [...]uint8{0, 3, 6, 11}
106
107 func (i Number) String() string {
108 i -= 1
109 if i < 0 || i >= Number(len(_Number_index)-1) {
110 return "Number(" + strconv.FormatInt(int64(i+1), 10) + ")"
111 }
112 return _Number_name[_Number_index[i]:_Number_index[i+1]]
113 }
114 `
115
116
117 const gap_in = `type Gap int
118 const (
119 Two Gap = 2
120 Three Gap = 3
121 Five Gap = 5
122 Six Gap = 6
123 Seven Gap = 7
124 Eight Gap = 8
125 Nine Gap = 9
126 Eleven Gap = 11
127 )
128 `
129
130 const gap_out = `func _() {
131 // An "invalid array index" compiler error signifies that the constant values have changed.
132 // Re-run the stringer command to generate them again.
133 var x [1]struct{}
134 _ = x[Two-2]
135 _ = x[Three-3]
136 _ = x[Five-5]
137 _ = x[Six-6]
138 _ = x[Seven-7]
139 _ = x[Eight-8]
140 _ = x[Nine-9]
141 _ = x[Eleven-11]
142 }
143
144 const (
145 _Gap_name_0 = "TwoThree"
146 _Gap_name_1 = "FiveSixSevenEightNine"
147 _Gap_name_2 = "Eleven"
148 )
149
150 var (
151 _Gap_index_0 = [...]uint8{0, 3, 8}
152 _Gap_index_1 = [...]uint8{0, 4, 7, 12, 17, 21}
153 )
154
155 func (i Gap) String() string {
156 switch {
157 case 2 <= i && i <= 3:
158 i -= 2
159 return _Gap_name_0[_Gap_index_0[i]:_Gap_index_0[i+1]]
160 case 5 <= i && i <= 9:
161 i -= 5
162 return _Gap_name_1[_Gap_index_1[i]:_Gap_index_1[i+1]]
163 case i == 11:
164 return _Gap_name_2
165 default:
166 return "Gap(" + strconv.FormatInt(int64(i), 10) + ")"
167 }
168 }
169 `
170
171
172 const num_in = `type Num int
173 const (
174 m_2 Num = -2 + iota
175 m_1
176 m0
177 m1
178 m2
179 )
180 `
181
182 const num_out = `func _() {
183 // An "invalid array index" compiler error signifies that the constant values have changed.
184 // Re-run the stringer command to generate them again.
185 var x [1]struct{}
186 _ = x[m_2 - -2]
187 _ = x[m_1 - -1]
188 _ = x[m0-0]
189 _ = x[m1-1]
190 _ = x[m2-2]
191 }
192
193 const _Num_name = "m_2m_1m0m1m2"
194
195 var _Num_index = [...]uint8{0, 3, 6, 8, 10, 12}
196
197 func (i Num) String() string {
198 i -= -2
199 if i < 0 || i >= Num(len(_Num_index)-1) {
200 return "Num(" + strconv.FormatInt(int64(i+-2), 10) + ")"
201 }
202 return _Num_name[_Num_index[i]:_Num_index[i+1]]
203 }
204 `
205
206
207 const unum_in = `type Unum uint
208 const (
209 m_2 Unum = iota + 253
210 m_1
211 )
212
213 const (
214 m0 Unum = iota
215 m1
216 m2
217 )
218 `
219
220 const unum_out = `func _() {
221 // An "invalid array index" compiler error signifies that the constant values have changed.
222 // Re-run the stringer command to generate them again.
223 var x [1]struct{}
224 _ = x[m_2-253]
225 _ = x[m_1-254]
226 _ = x[m0-0]
227 _ = x[m1-1]
228 _ = x[m2-2]
229 }
230
231 const (
232 _Unum_name_0 = "m0m1m2"
233 _Unum_name_1 = "m_2m_1"
234 )
235
236 var (
237 _Unum_index_0 = [...]uint8{0, 2, 4, 6}
238 _Unum_index_1 = [...]uint8{0, 3, 6}
239 )
240
241 func (i Unum) String() string {
242 switch {
243 case i <= 2:
244 return _Unum_name_0[_Unum_index_0[i]:_Unum_index_0[i+1]]
245 case 253 <= i && i <= 254:
246 i -= 253
247 return _Unum_name_1[_Unum_index_1[i]:_Unum_index_1[i+1]]
248 default:
249 return "Unum(" + strconv.FormatInt(int64(i), 10) + ")"
250 }
251 }
252 `
253
254
255 const unumpos_in = `type Unumpos uint
256 const (
257 m253 Unumpos = iota + 253
258 m254
259 )
260
261 const (
262 m1 Unumpos = iota + 1
263 m2
264 m3
265 )
266 `
267
268 const unumpos_out = `func _() {
269 // An "invalid array index" compiler error signifies that the constant values have changed.
270 // Re-run the stringer command to generate them again.
271 var x [1]struct{}
272 _ = x[m253-253]
273 _ = x[m254-254]
274 _ = x[m1-1]
275 _ = x[m2-2]
276 _ = x[m3-3]
277 }
278
279 const (
280 _Unumpos_name_0 = "m1m2m3"
281 _Unumpos_name_1 = "m253m254"
282 )
283
284 var (
285 _Unumpos_index_0 = [...]uint8{0, 2, 4, 6}
286 _Unumpos_index_1 = [...]uint8{0, 4, 8}
287 )
288
289 func (i Unumpos) String() string {
290 switch {
291 case 1 <= i && i <= 3:
292 i -= 1
293 return _Unumpos_name_0[_Unumpos_index_0[i]:_Unumpos_index_0[i+1]]
294 case 253 <= i && i <= 254:
295 i -= 253
296 return _Unumpos_name_1[_Unumpos_index_1[i]:_Unumpos_index_1[i+1]]
297 default:
298 return "Unumpos(" + strconv.FormatInt(int64(i), 10) + ")"
299 }
300 }
301 `
302
303
304
305 const prime_in = `type Prime int
306 const (
307 p2 Prime = 2
308 p3 Prime = 3
309 p5 Prime = 5
310 p7 Prime = 7
311 p77 Prime = 7 // Duplicate; note that p77 doesn't appear below.
312 p11 Prime = 11
313 p13 Prime = 13
314 p17 Prime = 17
315 p19 Prime = 19
316 p23 Prime = 23
317 p29 Prime = 29
318 p37 Prime = 31
319 p41 Prime = 41
320 p43 Prime = 43
321 )
322 `
323
324 const prime_out = `func _() {
325 // An "invalid array index" compiler error signifies that the constant values have changed.
326 // Re-run the stringer command to generate them again.
327 var x [1]struct{}
328 _ = x[p2-2]
329 _ = x[p3-3]
330 _ = x[p5-5]
331 _ = x[p7-7]
332 _ = x[p77-7]
333 _ = x[p11-11]
334 _ = x[p13-13]
335 _ = x[p17-17]
336 _ = x[p19-19]
337 _ = x[p23-23]
338 _ = x[p29-29]
339 _ = x[p37-31]
340 _ = x[p41-41]
341 _ = x[p43-43]
342 }
343
344 const _Prime_name = "p2p3p5p7p11p13p17p19p23p29p37p41p43"
345
346 var _Prime_map = map[Prime]string{
347 2: _Prime_name[0:2],
348 3: _Prime_name[2:4],
349 5: _Prime_name[4:6],
350 7: _Prime_name[6:8],
351 11: _Prime_name[8:11],
352 13: _Prime_name[11:14],
353 17: _Prime_name[14:17],
354 19: _Prime_name[17:20],
355 23: _Prime_name[20:23],
356 29: _Prime_name[23:26],
357 31: _Prime_name[26:29],
358 41: _Prime_name[29:32],
359 43: _Prime_name[32:35],
360 }
361
362 func (i Prime) String() string {
363 if str, ok := _Prime_map[i]; ok {
364 return str
365 }
366 return "Prime(" + strconv.FormatInt(int64(i), 10) + ")"
367 }
368 `
369
370 const prefix_in = `type Type int
371 const (
372 TypeInt Type = iota
373 TypeString
374 TypeFloat
375 TypeRune
376 TypeByte
377 TypeStruct
378 TypeSlice
379 )
380 `
381
382 const prefix_out = `func _() {
383 // An "invalid array index" compiler error signifies that the constant values have changed.
384 // Re-run the stringer command to generate them again.
385 var x [1]struct{}
386 _ = x[TypeInt-0]
387 _ = x[TypeString-1]
388 _ = x[TypeFloat-2]
389 _ = x[TypeRune-3]
390 _ = x[TypeByte-4]
391 _ = x[TypeStruct-5]
392 _ = x[TypeSlice-6]
393 }
394
395 const _Type_name = "IntStringFloatRuneByteStructSlice"
396
397 var _Type_index = [...]uint8{0, 3, 9, 14, 18, 22, 28, 33}
398
399 func (i Type) String() string {
400 if i < 0 || i >= Type(len(_Type_index)-1) {
401 return "Type(" + strconv.FormatInt(int64(i), 10) + ")"
402 }
403 return _Type_name[_Type_index[i]:_Type_index[i+1]]
404 }
405 `
406
407 const tokens_in = `type Token int
408 const (
409 And Token = iota // &
410 Or // |
411 Add // +
412 Sub // -
413 Ident
414 Period // .
415
416 // not to be used
417 SingleBefore
418 // not to be used
419 BeforeAndInline // inline
420 InlineGeneral /* inline general */
421 )
422 `
423
424 const tokens_out = `func _() {
425 // An "invalid array index" compiler error signifies that the constant values have changed.
426 // Re-run the stringer command to generate them again.
427 var x [1]struct{}
428 _ = x[And-0]
429 _ = x[Or-1]
430 _ = x[Add-2]
431 _ = x[Sub-3]
432 _ = x[Ident-4]
433 _ = x[Period-5]
434 _ = x[SingleBefore-6]
435 _ = x[BeforeAndInline-7]
436 _ = x[InlineGeneral-8]
437 }
438
439 const _Token_name = "&|+-Ident.SingleBeforeinlineinline general"
440
441 var _Token_index = [...]uint8{0, 1, 2, 3, 4, 9, 10, 22, 28, 42}
442
443 func (i Token) String() string {
444 if i < 0 || i >= Token(len(_Token_index)-1) {
445 return "Token(" + strconv.FormatInt(int64(i), 10) + ")"
446 }
447 return _Token_name[_Token_index[i]:_Token_index[i+1]]
448 }
449 `
450
451 func TestGolden(t *testing.T) {
452 testenv.NeedsTool(t, "go")
453
454 dir := t.TempDir()
455 for _, test := range golden {
456 test := test
457 t.Run(test.name, func(t *testing.T) {
458 g := Generator{
459 trimPrefix: test.trimPrefix,
460 lineComment: test.lineComment,
461 logf: t.Logf,
462 }
463 input := "package test\n" + test.input
464 file := test.name + ".go"
465 absFile := filepath.Join(dir, file)
466 err := os.WriteFile(absFile, []byte(input), 0644)
467 if err != nil {
468 t.Fatal(err)
469 }
470
471 g.parsePackage([]string{absFile}, nil)
472
473 tokens := strings.SplitN(test.input, " ", 3)
474 if len(tokens) != 3 {
475 t.Fatalf("%s: need type declaration on first line", test.name)
476 }
477 g.generate(tokens[1])
478 got := string(g.format())
479 if got != test.output {
480 t.Errorf("%s: got(%d)\n====\n%q====\nexpected(%d)\n====%q", test.name, len(got), got, len(test.output), test.output)
481 }
482 })
483 }
484 }
485
View as plain text