OLD | NEW |
| (Empty) |
1 // Copyright 2009 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 package datafmt | |
6 | |
7 import ( | |
8 "fmt" | |
9 "testing" | |
10 "go/token" | |
11 ) | |
12 | |
13 | |
14 var fset = token.NewFileSet() | |
15 | |
16 | |
17 func parse(t *testing.T, form string, fmap FormatterMap) Format { | |
18 f, err := Parse(fset, "", []byte(form), fmap) | |
19 if err != nil { | |
20 t.Errorf("Parse(%s): %v", form, err) | |
21 return nil | |
22 } | |
23 return f | |
24 } | |
25 | |
26 | |
27 func verify(t *testing.T, f Format, expected string, args ...interface{}) { | |
28 if f == nil { | |
29 return // allow other tests to run | |
30 } | |
31 result := f.Sprint(args...) | |
32 if result != expected { | |
33 t.Errorf( | |
34 "result : `%s`\nexpected: `%s`\n\n", | |
35 result, expected) | |
36 } | |
37 } | |
38 | |
39 | |
40 func formatter(s *State, value interface{}, rule_name string) bool { | |
41 switch rule_name { | |
42 case "/": | |
43 fmt.Fprintf(s, "%d %d %d", s.Pos().Line, s.LinePos().Column, s.P
os().Column) | |
44 return true | |
45 case "blank": | |
46 s.Write([]byte{' '}) | |
47 return true | |
48 case "int": | |
49 if value.(int)&1 == 0 { | |
50 fmt.Fprint(s, "even ") | |
51 } else { | |
52 fmt.Fprint(s, "odd ") | |
53 } | |
54 return true | |
55 case "nil": | |
56 return false | |
57 case "testing.T": | |
58 s.Write([]byte("testing.T")) | |
59 return true | |
60 } | |
61 panic("unreachable") | |
62 return false | |
63 } | |
64 | |
65 | |
66 func TestCustomFormatters(t *testing.T) { | |
67 fmap0 := FormatterMap{"/": formatter} | |
68 fmap1 := FormatterMap{"int": formatter, "blank": formatter, "nil": forma
tter} | |
69 fmap2 := FormatterMap{"testing.T": formatter} | |
70 | |
71 f := parse(t, `int=`, fmap0) | |
72 verify(t, f, ``, 1, 2, 3) | |
73 | |
74 f = parse(t, `int="#"`, nil) | |
75 verify(t, f, `###`, 1, 2, 3) | |
76 | |
77 f = parse(t, `int="#";string="%s"`, fmap0) | |
78 verify(t, f, "#1 0 1#1 0 7#1 0 13\n2 0 0foo2 0 8\n", 1, 2, 3, "\n", "foo
", "\n") | |
79 | |
80 f = parse(t, ``, fmap1) | |
81 verify(t, f, `even odd even odd `, 0, 1, 2, 3) | |
82 | |
83 f = parse(t, `/ =@:blank; float64="#"`, fmap1) | |
84 verify(t, f, `# # #`, 0.0, 1.0, 2.0) | |
85 | |
86 f = parse(t, `float64=@:nil`, fmap1) | |
87 verify(t, f, ``, 0.0, 1.0, 2.0) | |
88 | |
89 f = parse(t, `testing "testing"; ptr=*`, fmap2) | |
90 verify(t, f, `testing.T`, t) | |
91 | |
92 // TODO needs more tests | |
93 } | |
94 | |
95 | |
96 // ---------------------------------------------------------------------------- | |
97 // Formatting of basic and simple composite types | |
98 | |
99 func check(t *testing.T, form, expected string, args ...interface{}) { | |
100 f := parse(t, form, nil) | |
101 if f == nil { | |
102 return // allow other tests to run | |
103 } | |
104 result := f.Sprint(args...) | |
105 if result != expected { | |
106 t.Errorf( | |
107 "format : %s\nresult : `%s`\nexpected: `%s`\n\n", | |
108 form, result, expected) | |
109 } | |
110 } | |
111 | |
112 | |
113 func TestBasicTypes(t *testing.T) { | |
114 check(t, ``, ``) | |
115 check(t, `bool=":%v"`, `:true:false`, true, false) | |
116 check(t, `int="%b %d %o 0x%x"`, `101010 42 52 0x2a`, 42) | |
117 | |
118 check(t, `int="%"`, `%`, 42) | |
119 check(t, `int="%%"`, `%`, 42) | |
120 check(t, `int="**%%**"`, `**%**`, 42) | |
121 check(t, `int="%%%%%%"`, `%%%`, 42) | |
122 check(t, `int="%%%d%%"`, `%42%`, 42) | |
123 | |
124 const i = -42 | |
125 const is = `-42` | |
126 check(t, `int ="%d"`, is, i) | |
127 check(t, `int8 ="%d"`, is, int8(i)) | |
128 check(t, `int16="%d"`, is, int16(i)) | |
129 check(t, `int32="%d"`, is, int32(i)) | |
130 check(t, `int64="%d"`, is, int64(i)) | |
131 | |
132 const u = 42 | |
133 const us = `42` | |
134 check(t, `uint ="%d"`, us, uint(u)) | |
135 check(t, `uint8 ="%d"`, us, uint8(u)) | |
136 check(t, `uint16="%d"`, us, uint16(u)) | |
137 check(t, `uint32="%d"`, us, uint32(u)) | |
138 check(t, `uint64="%d"`, us, uint64(u)) | |
139 | |
140 const f = 3.141592 | |
141 const fs = `3.141592` | |
142 check(t, `float64="%g"`, fs, f) | |
143 check(t, `float32="%g"`, fs, float32(f)) | |
144 check(t, `float64="%g"`, fs, float64(f)) | |
145 } | |
146 | |
147 | |
148 func TestArrayTypes(t *testing.T) { | |
149 var a0 [10]int | |
150 check(t, `array="array";`, `array`, a0) | |
151 | |
152 a1 := [...]int{1, 2, 3} | |
153 check(t, `array="array";`, `array`, a1) | |
154 check(t, `array={*}; int="%d";`, `123`, a1) | |
155 check(t, `array={* / ", "}; int="%d";`, `1, 2, 3`, a1) | |
156 check(t, `array={* / *}; int="%d";`, `12233`, a1) | |
157 | |
158 a2 := []interface{}{42, "foo", 3.14} | |
159 check(t, `array={* / ", "}; interface=*; string="bar"; default="%v";`, `
42, bar, 3.14`, a2) | |
160 } | |
161 | |
162 | |
163 func TestChanTypes(t *testing.T) { | |
164 var c0 chan int | |
165 check(t, `chan="chan"`, `chan`, c0) | |
166 | |
167 c1 := make(chan int) | |
168 go func() { c1 <- 42 }() | |
169 check(t, `chan="chan"`, `chan`, c1) | |
170 // check(t, `chan=*`, `42`, c1); // reflection support for chans incomp
lete | |
171 } | |
172 | |
173 | |
174 func TestFuncTypes(t *testing.T) { | |
175 var f0 func() int | |
176 check(t, `func="func"`, `func`, f0) | |
177 | |
178 f1 := func() int { return 42 } | |
179 check(t, `func="func"`, `func`, f1) | |
180 // check(t, `func=*`, `42`, f1); // reflection support for funcs incomp
lete | |
181 } | |
182 | |
183 | |
184 func TestMapTypes(t *testing.T) { | |
185 var m0 map[string]int | |
186 check(t, `map="map"`, `map`, m0) | |
187 | |
188 m1 := map[string]int{} | |
189 check(t, `map="map"`, `map`, m1) | |
190 // check(t, `map=*`, ``, m1); // reflection support for maps incomplete | |
191 } | |
192 | |
193 | |
194 func TestPointerTypes(t *testing.T) { | |
195 var p0 *int | |
196 check(t, `ptr="ptr"`, `ptr`, p0) | |
197 check(t, `ptr=*`, ``, p0) | |
198 check(t, `ptr=*|"nil"`, `nil`, p0) | |
199 | |
200 x := 99991 | |
201 p1 := &x | |
202 check(t, `ptr="ptr"`, `ptr`, p1) | |
203 check(t, `ptr=*; int="%d"`, `99991`, p1) | |
204 } | |
205 | |
206 | |
207 func TestDefaultRule(t *testing.T) { | |
208 check(t, `default="%v"`, `42foo3.14`, 42, "foo", 3.14) | |
209 check(t, `default="%v"; int="%x"`, `abcdef`, 10, 11, 12, 13, 14, 15) | |
210 check(t, `default="%v"; int="%x"`, `ab**ef`, 10, 11, "**", 14, 15) | |
211 check(t, `default="%x"; int=@:default`, `abcdef`, 10, 11, 12, 13, 14, 15
) | |
212 } | |
213 | |
214 | |
215 func TestGlobalSeparatorRule(t *testing.T) { | |
216 check(t, `int="%d"; / ="-"`, `1-2-3-4`, 1, 2, 3, 4) | |
217 check(t, `int="%x%x"; / ="*"`, `aa*aa`, 10, 10) | |
218 } | |
219 | |
220 | |
221 // ---------------------------------------------------------------------------- | |
222 // Formatting of a struct | |
223 | |
224 type T1 struct { | |
225 a int | |
226 } | |
227 | |
228 const F1 = `datafmt "datafmt";` + | |
229 `int = "%d";` + | |
230 `datafmt.T1 = "<" a ">";` | |
231 | |
232 func TestStruct1(t *testing.T) { check(t, F1, "<42>", T1{42}) } | |
233 | |
234 | |
235 // ---------------------------------------------------------------------------- | |
236 // Formatting of a struct with an optional field (ptr) | |
237 | |
238 type T2 struct { | |
239 s string | |
240 p *T1 | |
241 } | |
242 | |
243 const F2a = F1 + | |
244 `string = "%s";` + | |
245 `ptr = *;` + | |
246 `datafmt.T2 = s ["-" p "-"];` | |
247 | |
248 const F2b = F1 + | |
249 `string = "%s";` + | |
250 `ptr = *;` + | |
251 `datafmt.T2 = s ("-" p "-" | "empty");` | |
252 | |
253 func TestStruct2(t *testing.T) { | |
254 check(t, F2a, "foo", T2{"foo", nil}) | |
255 check(t, F2a, "bar-<17>-", T2{"bar", &T1{17}}) | |
256 check(t, F2b, "fooempty", T2{"foo", nil}) | |
257 } | |
258 | |
259 | |
260 // ---------------------------------------------------------------------------- | |
261 // Formatting of a struct with a repetitive field (slice) | |
262 | |
263 type T3 struct { | |
264 s string | |
265 a []int | |
266 } | |
267 | |
268 const F3a = `datafmt "datafmt";` + | |
269 `default = "%v";` + | |
270 `array = *;` + | |
271 `datafmt.T3 = s {" " a a / ","};` | |
272 | |
273 const F3b = `datafmt "datafmt";` + | |
274 `int = "%d";` + | |
275 `string = "%s";` + | |
276 `array = *;` + | |
277 `nil = ;` + | |
278 `empty = *:nil;` + | |
279 `datafmt.T3 = s [a:empty ": " {a / "-"}]` | |
280 | |
281 func TestStruct3(t *testing.T) { | |
282 check(t, F3a, "foo", T3{"foo", nil}) | |
283 check(t, F3a, "foo 00, 11, 22", T3{"foo", []int{0, 1, 2}}) | |
284 check(t, F3b, "bar", T3{"bar", nil}) | |
285 check(t, F3b, "bal: 2-3-5", T3{"bal", []int{2, 3, 5}}) | |
286 } | |
287 | |
288 | |
289 // ---------------------------------------------------------------------------- | |
290 // Formatting of a struct with alternative field | |
291 | |
292 type T4 struct { | |
293 x *int | |
294 a []int | |
295 } | |
296 | |
297 const F4a = `datafmt "datafmt";` + | |
298 `int = "%d";` + | |
299 `ptr = *;` + | |
300 `array = *;` + | |
301 `nil = ;` + | |
302 `empty = *:nil;` + | |
303 `datafmt.T4 = "<" (x:empty x | "-") ">" ` | |
304 | |
305 const F4b = `datafmt "datafmt";` + | |
306 `int = "%d";` + | |
307 `ptr = *;` + | |
308 `array = *;` + | |
309 `nil = ;` + | |
310 `empty = *:nil;` + | |
311 `datafmt.T4 = "<" (a:empty {a / ", "} | "-") ">" ` | |
312 | |
313 func TestStruct4(t *testing.T) { | |
314 x := 7 | |
315 check(t, F4a, "<->", T4{nil, nil}) | |
316 check(t, F4a, "<7>", T4{&x, nil}) | |
317 check(t, F4b, "<->", T4{nil, nil}) | |
318 check(t, F4b, "<2, 3, 7>", T4{nil, []int{2, 3, 7}}) | |
319 } | |
320 | |
321 | |
322 // ---------------------------------------------------------------------------- | |
323 // Formatting a struct (documentation example) | |
324 | |
325 type Point struct { | |
326 name string | |
327 x, y int | |
328 } | |
329 | |
330 const FPoint = `datafmt "datafmt";` + | |
331 `int = "%d";` + | |
332 `hexInt = "0x%x";` + | |
333 `string = "---%s---";` + | |
334 `datafmt.Point = name "{" x ", " y:hexInt "}";` | |
335 | |
336 func TestStructPoint(t *testing.T) { | |
337 p := Point{"foo", 3, 15} | |
338 check(t, FPoint, "---foo---{3, 0xf}", p) | |
339 } | |
340 | |
341 | |
342 // ---------------------------------------------------------------------------- | |
343 // Formatting a slice (documentation example) | |
344 | |
345 const FSlice = `int = "%b";` + | |
346 `array = { * / ", " }` | |
347 | |
348 func TestSlice(t *testing.T) { check(t, FSlice, "10, 11, 101, 111", []int{2, 3,
5, 7}) } | |
349 | |
350 | |
351 // TODO add more tests | |
OLD | NEW |