Source file src/pkg/fmt/fmt_test.go
1
2
3
4
5 package fmt_test
6
7 import (
8 "bytes"
9 . "fmt"
10 "io"
11 "math"
12 "runtime"
13 "strings"
14 "testing"
15 "time"
16 "unicode"
17 )
18
19 type (
20 renamedBool bool
21 renamedInt int
22 renamedInt8 int8
23 renamedInt16 int16
24 renamedInt32 int32
25 renamedInt64 int64
26 renamedUint uint
27 renamedUint8 uint8
28 renamedUint16 uint16
29 renamedUint32 uint32
30 renamedUint64 uint64
31 renamedUintptr uintptr
32 renamedString string
33 renamedBytes []byte
34 renamedFloat32 float32
35 renamedFloat64 float64
36 renamedComplex64 complex64
37 renamedComplex128 complex128
38 )
39
40 func TestFmtInterface(t *testing.T) {
41 var i1 interface{}
42 i1 = "abc"
43 s := Sprintf("%s", i1)
44 if s != "abc" {
45 t.Errorf(`Sprintf("%%s", empty("abc")) = %q want %q`, s, "abc")
46 }
47 }
48
49 const b32 uint32 = 1<<32 - 1
50 const b64 uint64 = 1<<64 - 1
51
52 var array = [5]int{1, 2, 3, 4, 5}
53 var iarray = [4]interface{}{1, "hello", 2.5, nil}
54 var slice = array[:]
55 var islice = iarray[:]
56
57 type A struct {
58 i int
59 j uint
60 s string
61 x []int
62 }
63
64 type I int
65
66 func (i I) String() string { return Sprintf("<%d>", int(i)) }
67
68 type B struct {
69 I I
70 j int
71 }
72
73 type C struct {
74 i int
75 B
76 }
77
78 type F int
79
80 func (f F) Format(s State, c rune) {
81 Fprintf(s, "<%c=F(%d)>", c, int(f))
82 }
83
84 type G int
85
86 func (g G) GoString() string {
87 return Sprintf("GoString(%d)", int(g))
88 }
89
90 type S struct {
91 F F
92 G G
93 }
94
95 type SI struct {
96 I interface{}
97 }
98
99
100 type P int
101
102 var pValue P
103
104 func (p *P) String() string {
105 return "String(p)"
106 }
107
108 var barray = [5]renamedUint8{1, 2, 3, 4, 5}
109 var bslice = barray[:]
110
111 var b byte
112
113 var fmttests = []struct {
114 fmt string
115 val interface{}
116 out string
117 }{
118 {"%d", 12345, "12345"},
119 {"%v", 12345, "12345"},
120 {"%t", true, "true"},
121
122
123 {"%s", "abc", "abc"},
124 {"%x", "abc", "616263"},
125 {"%x", "xyz", "78797a"},
126 {"%X", "xyz", "78797A"},
127 {"%q", "abc", `"abc"`},
128
129
130 {"%s", []byte("abc"), "abc"},
131 {"%x", []byte("abc"), "616263"},
132 {"% x", []byte("abc\xff"), "61 62 63 ff"},
133 {"%#x", []byte("abc\xff"), "0x610x620x630xff"},
134 {"%#X", []byte("abc\xff"), "0X610X620X630XFF"},
135 {"%# x", []byte("abc\xff"), "0x61 0x62 0x63 0xff"},
136 {"%# X", []byte("abc\xff"), "0X61 0X62 0X63 0XFF"},
137 {"% X", []byte("abc\xff"), "61 62 63 FF"},
138 {"%x", []byte("xyz"), "78797a"},
139 {"%X", []byte("xyz"), "78797A"},
140 {"%q", []byte("abc"), `"abc"`},
141
142
143 {"%#q", `abc`, "`abc`"},
144 {"%#q", `"`, "`\"`"},
145 {"1 %#q", `\n`, "1 `\\n`"},
146 {"2 %#q", "\n", `2 "\n"`},
147 {"%q", `"`, `"\""`},
148 {"%q", "\a\b\f\r\n\t\v", `"\a\b\f\r\n\t\v"`},
149 {"%q", "abc\xffdef", `"abc\xffdef"`},
150 {"%q", "\u263a", `"☺"`},
151 {"%+q", "\u263a", `"\u263a"`},
152 {"%q", "\U0010ffff", `"\U0010ffff"`},
153
154
155 {"%q", 'x', `'x'`},
156 {"%q", 0, `'\x00'`},
157 {"%q", '\n', `'\n'`},
158 {"%q", '\u0e00', `'\u0e00'`},
159 {"%q", '\U000c2345', `'\U000c2345'`},
160 {"%q", int64(0x7FFFFFFF), `%!q(int64=2147483647)`},
161 {"%q", uint64(0xFFFFFFFF), `%!q(uint64=4294967295)`},
162 {"%q", '"', `'"'`},
163 {"%q", '\'', `'\''`},
164 {"%q", "\u263a", `"☺"`},
165 {"%+q", "\u263a", `"\u263a"`},
166
167
168 {"%5s", "abc", " abc"},
169 {"%2s", "\u263a", " ☺"},
170 {"%-5s", "abc", "abc "},
171 {"%-8q", "abc", `"abc" `},
172 {"%05s", "abc", "00abc"},
173 {"%08q", "abc", `000"abc"`},
174 {"%5s", "abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"},
175 {"%.5s", "abcdefghijklmnopqrstuvwxyz", "abcde"},
176 {"%.5s", "日本語日本語", "日本語日本"},
177 {"%.5s", []byte("日本語日本語"), "日本語日本"},
178 {"%.5q", "abcdefghijklmnopqrstuvwxyz", `"abcde"`},
179 {"%.3q", "日本語日本語", `"日本語"`},
180 {"%.3q", []byte("日本語日本語"), `"日本語"`},
181 {"%10.1q", "日本語日本語", ` "日"`},
182 {"%10v", nil, " <nil>"},
183 {"%-10v", nil, "<nil> "},
184
185
186 {"%d", 12345, "12345"},
187 {"%d", -12345, "-12345"},
188 {"%10d", 12345, " 12345"},
189 {"%10d", -12345, " -12345"},
190 {"%+10d", 12345, " +12345"},
191 {"%010d", 12345, "0000012345"},
192 {"%010d", -12345, "-000012345"},
193 {"%-10d", 12345, "12345 "},
194 {"%010.3d", 1, " 001"},
195 {"%010.3d", -1, " -001"},
196 {"%+d", 12345, "+12345"},
197 {"%+d", -12345, "-12345"},
198 {"%+d", 0, "+0"},
199 {"% d", 0, " 0"},
200 {"% d", 12345, " 12345"},
201 {"%.0d", 0, ""},
202 {"%.d", 0, ""},
203
204
205 {"%U", 0x1, "U+0001"},
206 {"%U", uint(0x1), "U+0001"},
207 {"%.8U", 0x2, "U+00000002"},
208 {"%U", 0x1234, "U+1234"},
209 {"%U", 0x12345, "U+12345"},
210 {"%10.6U", 0xABC, " U+000ABC"},
211 {"%-10.6U", 0xABC, "U+000ABC "},
212 {"%U", '\n', `U+000A`},
213 {"%#U", '\n', `U+000A`},
214 {"%U", 'x', `U+0078`},
215 {"%#U", 'x', `U+0078 'x'`},
216 {"%U", '\u263a', `U+263A`},
217 {"%#U", '\u263a', `U+263A '☺'`},
218
219
220 {"%+.3e", 0.0, "+0.000e+00"},
221 {"%+.3e", 1.0, "+1.000e+00"},
222 {"%+.3f", -1.0, "-1.000"},
223 {"% .3E", -1.0, "-1.000E+00"},
224 {"% .3e", 1.0, " 1.000e+00"},
225 {"%+.3g", 0.0, "+0"},
226 {"%+.3g", 1.0, "+1"},
227 {"%+.3g", -1.0, "-1"},
228 {"% .3g", -1.0, "-1"},
229 {"% .3g", 1.0, " 1"},
230
231
232 {"%+.3e", 0i, "(+0.000e+00+0.000e+00i)"},
233 {"%+.3f", 0i, "(+0.000+0.000i)"},
234 {"%+.3g", 0i, "(+0+0i)"},
235 {"%+.3e", 1 + 2i, "(+1.000e+00+2.000e+00i)"},
236 {"%+.3f", 1 + 2i, "(+1.000+2.000i)"},
237 {"%+.3g", 1 + 2i, "(+1+2i)"},
238 {"%.3e", 0i, "(0.000e+00+0.000e+00i)"},
239 {"%.3f", 0i, "(0.000+0.000i)"},
240 {"%.3g", 0i, "(0+0i)"},
241 {"%.3e", 1 + 2i, "(1.000e+00+2.000e+00i)"},
242 {"%.3f", 1 + 2i, "(1.000+2.000i)"},
243 {"%.3g", 1 + 2i, "(1+2i)"},
244 {"%.3e", -1 - 2i, "(-1.000e+00-2.000e+00i)"},
245 {"%.3f", -1 - 2i, "(-1.000-2.000i)"},
246 {"%.3g", -1 - 2i, "(-1-2i)"},
247 {"% .3E", -1 - 2i, "(-1.000E+00-2.000E+00i)"},
248 {"%+.3g", complex64(1 + 2i), "(+1+2i)"},
249 {"%+.3g", complex128(1 + 2i), "(+1+2i)"},
250
251
252 {"", 2, "%!(EXTRA int=2)"},
253 {"%d", "hello", "%!d(string=hello)"},
254
255
256 {"%d", 1234, "1234"},
257 {"%d", -1234, "-1234"},
258 {"%d", uint(1234), "1234"},
259 {"%d", uint32(b32), "4294967295"},
260 {"%d", uint64(b64), "18446744073709551615"},
261 {"%o", 01234, "1234"},
262 {"%#o", 01234, "01234"},
263 {"%o", uint32(b32), "37777777777"},
264 {"%o", uint64(b64), "1777777777777777777777"},
265 {"%x", 0x1234abcd, "1234abcd"},
266 {"%#x", 0x1234abcd, "0x1234abcd"},
267 {"%x", b32 - 0x1234567, "fedcba98"},
268 {"%X", 0x1234abcd, "1234ABCD"},
269 {"%X", b32 - 0x1234567, "FEDCBA98"},
270 {"%#X", 0, "0X0"},
271 {"%x", b64, "ffffffffffffffff"},
272 {"%b", 7, "111"},
273 {"%b", b64, "1111111111111111111111111111111111111111111111111111111111111111"},
274 {"%b", -6, "-110"},
275 {"%e", 1.0, "1.000000e+00"},
276 {"%e", 1234.5678e3, "1.234568e+06"},
277 {"%e", 1234.5678e-8, "1.234568e-05"},
278 {"%e", -7.0, "-7.000000e+00"},
279 {"%e", -1e-9, "-1.000000e-09"},
280 {"%f", 1234.5678e3, "1234567.800000"},
281 {"%f", 1234.5678e-8, "0.000012"},
282 {"%f", -7.0, "-7.000000"},
283 {"%f", -1e-9, "-0.000000"},
284 {"%g", 1234.5678e3, "1.2345678e+06"},
285 {"%g", float32(1234.5678e3), "1.2345678e+06"},
286 {"%g", 1234.5678e-8, "1.2345678e-05"},
287 {"%g", -7.0, "-7"},
288 {"%g", -1e-9, "-1e-09"},
289 {"%g", float32(-1e-9), "-1e-09"},
290 {"%E", 1.0, "1.000000E+00"},
291 {"%E", 1234.5678e3, "1.234568E+06"},
292 {"%E", 1234.5678e-8, "1.234568E-05"},
293 {"%E", -7.0, "-7.000000E+00"},
294 {"%E", -1e-9, "-1.000000E-09"},
295 {"%G", 1234.5678e3, "1.2345678E+06"},
296 {"%G", float32(1234.5678e3), "1.2345678E+06"},
297 {"%G", 1234.5678e-8, "1.2345678E-05"},
298 {"%G", -7.0, "-7"},
299 {"%G", -1e-9, "-1E-09"},
300 {"%G", float32(-1e-9), "-1E-09"},
301 {"%c", 'x', "x"},
302 {"%c", 0xe4, "ä"},
303 {"%c", 0x672c, "本"},
304 {"%c", '日', "日"},
305 {"%20.8d", 1234, " 00001234"},
306 {"%20.8d", -1234, " -00001234"},
307 {"%20d", 1234, " 1234"},
308 {"%-20.8d", 1234, "00001234 "},
309 {"%-20.8d", -1234, "-00001234 "},
310 {"%-#20.8x", 0x1234abc, "0x01234abc "},
311 {"%-#20.8X", 0x1234abc, "0X01234ABC "},
312 {"%-#20.8o", 01234, "00001234 "},
313 {"%.20b", 7, "00000000000000000111"},
314 {"%20.5s", "qwertyuiop", " qwert"},
315 {"%.5s", "qwertyuiop", "qwert"},
316 {"%-20.5s", "qwertyuiop", "qwert "},
317 {"%20c", 'x', " x"},
318 {"%-20c", 'x', "x "},
319 {"%20.6e", 1.2345e3, " 1.234500e+03"},
320 {"%20.6e", 1.2345e-3, " 1.234500e-03"},
321 {"%20e", 1.2345e3, " 1.234500e+03"},
322 {"%20e", 1.2345e-3, " 1.234500e-03"},
323 {"%20.8e", 1.2345e3, " 1.23450000e+03"},
324 {"%20f", 1.23456789e3, " 1234.567890"},
325 {"%20f", 1.23456789e-3, " 0.001235"},
326 {"%20f", 12345678901.23456789, " 12345678901.234568"},
327 {"%-20f", 1.23456789e3, "1234.567890 "},
328 {"%20.8f", 1.23456789e3, " 1234.56789000"},
329 {"%20.8f", 1.23456789e-3, " 0.00123457"},
330 {"%g", 1.23456789e3, "1234.56789"},
331 {"%g", 1.23456789e-3, "0.00123456789"},
332 {"%g", 1.23456789e20, "1.23456789e+20"},
333 {"%20e", math.Inf(1), " +Inf"},
334 {"%-20f", math.Inf(-1), "-Inf "},
335 {"%20g", math.NaN(), " NaN"},
336
337
338 {"%v", array, "[1 2 3 4 5]"},
339 {"%v", iarray, "[1 hello 2.5 <nil>]"},
340 {"%v", barray, "[1 2 3 4 5]"},
341 {"%v", &array, "&[1 2 3 4 5]"},
342 {"%v", &iarray, "&[1 hello 2.5 <nil>]"},
343 {"%v", &barray, "&[1 2 3 4 5]"},
344
345
346 {"%v", slice, "[1 2 3 4 5]"},
347 {"%v", islice, "[1 hello 2.5 <nil>]"},
348 {"%v", bslice, "[1 2 3 4 5]"},
349 {"%v", &slice, "&[1 2 3 4 5]"},
350 {"%v", &islice, "&[1 hello 2.5 <nil>]"},
351 {"%v", &bslice, "&[1 2 3 4 5]"},
352
353
354 {"%v", 1 + 2i, "(1+2i)"},
355 {"%v", complex64(1 + 2i), "(1+2i)"},
356 {"%v", complex128(1 + 2i), "(1+2i)"},
357
358
359 {"%v", A{1, 2, "a", []int{1, 2}}, `{1 2 a [1 2]}`},
360 {"%+v", A{1, 2, "a", []int{1, 2}}, `{i:1 j:2 s:a x:[1 2]}`},
361
362
363 {"%+v", B{1, 2}, `{I:<1> j:2}`},
364 {"%+v", C{1, B{2, 3}}, `{i:1 B:{I:<2> j:3}}`},
365
366
367 {"%s", I(23), `<23>`},
368 {"%q", I(23), `"<23>"`},
369 {"%x", I(23), `3c32333e`},
370 {"%#x", I(23), `0x3c0x320x330x3e`},
371 {"%# x", I(23), `0x3c 0x32 0x33 0x3e`},
372 {"%d", I(23), `23`},
373
374
375 {"%#v", A{1, 2, "a", []int{1, 2}}, `fmt_test.A{i:1, j:0x2, s:"a", x:[]int{1, 2}}`},
376 {"%#v", &b, "(*uint8)(0xPTR)"},
377 {"%#v", TestFmtInterface, "(func(*testing.T))(0xPTR)"},
378 {"%#v", make(chan int), "(chan int)(0xPTR)"},
379 {"%#v", uint64(1<<64 - 1), "0xffffffffffffffff"},
380 {"%#v", 1000000000, "1000000000"},
381 {"%#v", map[string]int{"a": 1}, `map[string]int{"a":1}`},
382 {"%#v", map[string]B{"a": {1, 2}}, `map[string]fmt_test.B{"a":fmt_test.B{I:1, j:2}}`},
383 {"%#v", []string{"a", "b"}, `[]string{"a", "b"}`},
384 {"%#v", SI{}, `fmt_test.SI{I:interface {}(nil)}`},
385 {"%#v", []int(nil), `[]int(nil)`},
386 {"%#v", []int{}, `[]int{}`},
387 {"%#v", array, `[5]int{1, 2, 3, 4, 5}`},
388 {"%#v", &array, `&[5]int{1, 2, 3, 4, 5}`},
389 {"%#v", iarray, `[4]interface {}{1, "hello", 2.5, interface {}(nil)}`},
390 {"%#v", &iarray, `&[4]interface {}{1, "hello", 2.5, interface {}(nil)}`},
391 {"%#v", map[int]byte(nil), `map[int]uint8(nil)`},
392 {"%#v", map[int]byte{}, `map[int]uint8{}`},
393 {"%#v", "foo", `"foo"`},
394 {"%#v", barray, `[5]fmt_test.renamedUint8{0x1, 0x2, 0x3, 0x4, 0x5}`},
395 {"%#v", bslice, `[]fmt_test.renamedUint8{0x1, 0x2, 0x3, 0x4, 0x5}`},
396
397
398 {"%#x", []int{1, 2, 15}, `[0x1 0x2 0xf]`},
399 {"%x", []int{1, 2, 15}, `[1 2 f]`},
400 {"%d", []int{1, 2, 15}, `[1 2 15]`},
401 {"%d", []byte{1, 2, 15}, `[1 2 15]`},
402 {"%q", []string{"a", "b"}, `["a" "b"]`},
403
404
405 {"%v", renamedBool(true), "true"},
406 {"%d", renamedBool(true), "%!d(fmt_test.renamedBool=true)"},
407 {"%o", renamedInt(8), "10"},
408 {"%d", renamedInt8(-9), "-9"},
409 {"%v", renamedInt16(10), "10"},
410 {"%v", renamedInt32(-11), "-11"},
411 {"%X", renamedInt64(255), "FF"},
412 {"%v", renamedUint(13), "13"},
413 {"%o", renamedUint8(14), "16"},
414 {"%X", renamedUint16(15), "F"},
415 {"%d", renamedUint32(16), "16"},
416 {"%X", renamedUint64(17), "11"},
417 {"%o", renamedUintptr(18), "22"},
418 {"%x", renamedString("thing"), "7468696e67"},
419 {"%d", renamedBytes([]byte{1, 2, 15}), `[1 2 15]`},
420 {"%q", renamedBytes([]byte("hello")), `"hello"`},
421 {"%x", []renamedUint8{'a', 'b', 'c'}, "616263"},
422 {"%s", []renamedUint8{'h', 'e', 'l', 'l', 'o'}, "hello"},
423 {"%q", []renamedUint8{'h', 'e', 'l', 'l', 'o'}, `"hello"`},
424 {"%v", renamedFloat32(22), "22"},
425 {"%v", renamedFloat64(33), "33"},
426 {"%v", renamedComplex64(3 + 4i), "(3+4i)"},
427 {"%v", renamedComplex128(4 - 3i), "(4-3i)"},
428
429
430 {"%x", F(1), "<x=F(1)>"},
431 {"%x", G(2), "2"},
432 {"%+v", S{F(4), G(5)}, "{F:<v=F(4)> G:5}"},
433
434
435 {"%#v", G(6), "GoString(6)"},
436 {"%#v", S{F(7), G(8)}, "fmt_test.S{F:<v=F(7)>, G:GoString(8)}"},
437
438
439 {"%T", (4 - 3i), "complex128"},
440 {"%T", renamedComplex128(4 - 3i), "fmt_test.renamedComplex128"},
441 {"%T", intVal, "int"},
442 {"%6T", &intVal, " *int"},
443 {"%10T", nil, " <nil>"},
444 {"%-10T", nil, "<nil> "},
445
446
447 {"p0=%p", new(int), "p0=0xPTR"},
448 {"p1=%s", &pValue, "p1=String(p)"},
449 {"p2=%p", &pValue, "p2=0xPTR"},
450 {"p3=%p", (*int)(nil), "p3=0x0"},
451 {"p4=%#p", new(int), "p4=PTR"},
452
453
454 {"%p", make(chan int), "0xPTR"},
455 {"%p", make(map[int]int), "0xPTR"},
456 {"%p", make([]int, 1), "0xPTR"},
457 {"%p", 27, "%!p(int=27)"},
458
459
460 {"%q", (*int)(nil), "%!q(*int=<nil>)"},
461 {"%q", new(int), "%!q(*int=0xPTR)"},
462
463
464 {"%v", (*int)(nil), "<nil>"},
465 {"%v", new(int), "0xPTR"},
466
467
468 {"%d", new(int), "PTR_d"},
469 {"%o", new(int), "PTR_o"},
470 {"%x", new(int), "PTR_x"},
471
472
473 {"%s", time.Time{}.Month(), "January"},
474 {"%d", time.Time{}.Month(), "1"},
475
476
477 {"%s %", "hello", "hello %!(NOVERB)"},
478 {"%s %.2", "hello", "hello %!(NOVERB)"},
479 {"%d", "hello", "%!d(string=hello)"},
480 {"no args", "hello", "no args%!(EXTRA string=hello)"},
481 {"%s", nil, "%!s(<nil>)"},
482 {"%T", nil, "<nil>"},
483 {"%-1", 100, "%!(NOVERB)%!(EXTRA int=100)"},
484
485
486
487
488
489
490
491 {"%v", map[float64]int{math.NaN(): 1, math.NaN(): 2}, "map[NaN:<nil> NaN:<nil>]"},
492
493
494 {"%b", int64(-1 << 63), "-1000000000000000000000000000000000000000000000000000000000000000"},
495
496
497
498 {"%v", []complex64{1, 2, 3}, "[(1+0i) (2+0i) (3+0i)]"},
499 {"%v", []complex128{1, 2, 3}, "[(1+0i) (2+0i) (3+0i)]"},
500
501
502 {"%.", 3, "%!.(int=3)"},
503 }
504
505 func TestSprintf(t *testing.T) {
506 for _, tt := range fmttests {
507 s := Sprintf(tt.fmt, tt.val)
508 if i := strings.Index(tt.out, "PTR"); i >= 0 {
509 pattern := "PTR"
510 chars := "0123456789abcdefABCDEF"
511 switch {
512 case strings.HasPrefix(tt.out[i:], "PTR_d"):
513 pattern = "PTR_d"
514 chars = chars[:10]
515 case strings.HasPrefix(tt.out[i:], "PTR_o"):
516 pattern = "PTR_o"
517 chars = chars[:8]
518 case strings.HasPrefix(tt.out[i:], "PTR_x"):
519 pattern = "PTR_x"
520 }
521 j := i
522 for ; j < len(s); j++ {
523 c := s[j]
524 if !strings.ContainsRune(chars, rune(c)) {
525 break
526 }
527 }
528 s = s[0:i] + pattern + s[j:]
529 }
530 if s != tt.out {
531 if _, ok := tt.val.(string); ok {
532
533
534 t.Errorf("Sprintf(%q, %q) = <%s> want <%s>", tt.fmt, tt.val, s, tt.out)
535 } else {
536 t.Errorf("Sprintf(%q, %v) = %q want %q", tt.fmt, tt.val, s, tt.out)
537 }
538 }
539 }
540 }
541
542 func BenchmarkSprintfEmpty(b *testing.B) {
543 for i := 0; i < b.N; i++ {
544 Sprintf("")
545 }
546 }
547
548 func BenchmarkSprintfString(b *testing.B) {
549 for i := 0; i < b.N; i++ {
550 Sprintf("%s", "hello")
551 }
552 }
553
554 func BenchmarkSprintfInt(b *testing.B) {
555 for i := 0; i < b.N; i++ {
556 Sprintf("%d", 5)
557 }
558 }
559
560 func BenchmarkSprintfIntInt(b *testing.B) {
561 for i := 0; i < b.N; i++ {
562 Sprintf("%d %d", 5, 6)
563 }
564 }
565
566 func BenchmarkSprintfPrefixedInt(b *testing.B) {
567 for i := 0; i < b.N; i++ {
568 Sprintf("This is some meaningless prefix text that needs to be scanned %d", 6)
569 }
570 }
571
572 func BenchmarkSprintfFloat(b *testing.B) {
573 for i := 0; i < b.N; i++ {
574 Sprintf("%g", 5.23184)
575 }
576 }
577
578 func BenchmarkManyArgs(b *testing.B) {
579 var buf bytes.Buffer
580 for i := 0; i < b.N; i++ {
581 buf.Reset()
582 Fprintf(&buf, "%2d/%2d/%2d %d:%d:%d %s %s\n", 3, 4, 5, 11, 12, 13, "hello", "world")
583 }
584 }
585
586 var mallocBuf bytes.Buffer
587
588 var mallocTest = []struct {
589 count int
590 desc string
591 fn func()
592 }{
593 {0, `Sprintf("")`, func() { Sprintf("") }},
594 {1, `Sprintf("xxx")`, func() { Sprintf("xxx") }},
595 {1, `Sprintf("%x")`, func() { Sprintf("%x", 7) }},
596 {2, `Sprintf("%s")`, func() { Sprintf("%s", "hello") }},
597 {1, `Sprintf("%x %x")`, func() { Sprintf("%x %x", 7, 112) }},
598
599
600 {2, `Sprintf("%g")`, func() { Sprintf("%g", float32(3.14159)) }},
601 {0, `Fprintf(buf, "%x %x %x")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%x %x %x", 7, 8, 9) }},
602 {1, `Fprintf(buf, "%s")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%s", "hello") }},
603 }
604
605 var _ bytes.Buffer
606
607 func TestCountMallocs(t *testing.T) {
608 if runtime.GOMAXPROCS(0) > 1 {
609 t.Skip("skipping; GOMAXPROCS>1")
610 }
611 for _, mt := range mallocTest {
612 mallocs := testing.AllocsPerRun(100, mt.fn)
613 if got, max := mallocs, float64(mt.count); got > max {
614 t.Errorf("%s: got %v allocs, want <=%v", mt.desc, got, max)
615 }
616 }
617 }
618
619 type flagPrinter struct{}
620
621 func (*flagPrinter) Format(f State, c rune) {
622 s := "%"
623 for i := 0; i < 128; i++ {
624 if f.Flag(i) {
625 s += string(i)
626 }
627 }
628 if w, ok := f.Width(); ok {
629 s += Sprintf("%d", w)
630 }
631 if p, ok := f.Precision(); ok {
632 s += Sprintf(".%d", p)
633 }
634 s += string(c)
635 io.WriteString(f, "["+s+"]")
636 }
637
638 var flagtests = []struct {
639 in string
640 out string
641 }{
642 {"%a", "[%a]"},
643 {"%-a", "[%-a]"},
644 {"%+a", "[%+a]"},
645 {"%#a", "[%#a]"},
646 {"% a", "[% a]"},
647 {"%0a", "[%0a]"},
648 {"%1.2a", "[%1.2a]"},
649 {"%-1.2a", "[%-1.2a]"},
650 {"%+1.2a", "[%+1.2a]"},
651 {"%-+1.2a", "[%+-1.2a]"},
652 {"%-+1.2abc", "[%+-1.2a]bc"},
653 {"%-1.2abc", "[%-1.2a]bc"},
654 }
655
656 func TestFlagParser(t *testing.T) {
657 var flagprinter flagPrinter
658 for _, tt := range flagtests {
659 s := Sprintf(tt.in, &flagprinter)
660 if s != tt.out {
661 t.Errorf("Sprintf(%q, &flagprinter) => %q, want %q", tt.in, s, tt.out)
662 }
663 }
664 }
665
666 func TestStructPrinter(t *testing.T) {
667 var s struct {
668 a string
669 b string
670 c int
671 }
672 s.a = "abc"
673 s.b = "def"
674 s.c = 123
675 var tests = []struct {
676 fmt string
677 out string
678 }{
679 {"%v", "{abc def 123}"},
680 {"%+v", "{a:abc b:def c:123}"},
681 }
682 for _, tt := range tests {
683 out := Sprintf(tt.fmt, s)
684 if out != tt.out {
685 t.Errorf("Sprintf(%q, &s) = %q, want %q", tt.fmt, out, tt.out)
686 }
687 }
688 }
689
690
691
692 func presentInMap(s string, a []string, t *testing.T) {
693 for i := 0; i < len(a); i++ {
694 loc := strings.Index(s, a[i])
695 if loc < 0 {
696 t.Errorf("map print: expected to find %q in %q", a[i], s)
697 }
698
699 loc += len(a[i])
700 if loc >= len(s) || (s[loc] != ' ' && s[loc] != ']') {
701 t.Errorf("map print: %q not properly terminated in %q", a[i], s)
702 }
703 }
704 }
705
706 func TestMapPrinter(t *testing.T) {
707 m0 := make(map[int]string)
708 s := Sprint(m0)
709 if s != "map[]" {
710 t.Errorf("empty map printed as %q not %q", s, "map[]")
711 }
712 m1 := map[int]string{1: "one", 2: "two", 3: "three"}
713 a := []string{"1:one", "2:two", "3:three"}
714 presentInMap(Sprintf("%v", m1), a, t)
715 presentInMap(Sprint(m1), a, t)
716 }
717
718 func TestEmptyMap(t *testing.T) {
719 const emptyMapStr = "map[]"
720 var m map[string]int
721 s := Sprint(m)
722 if s != emptyMapStr {
723 t.Errorf("nil map printed as %q not %q", s, emptyMapStr)
724 }
725 m = make(map[string]int)
726 s = Sprint(m)
727 if s != emptyMapStr {
728 t.Errorf("empty map printed as %q not %q", s, emptyMapStr)
729 }
730 }
731
732
733
734 func TestBlank(t *testing.T) {
735 got := Sprint("<", 1, ">:", 1, 2, 3, "!")
736 expect := "<1>:1 2 3!"
737 if got != expect {
738 t.Errorf("got %q expected %q", got, expect)
739 }
740 }
741
742
743
744 func TestBlankln(t *testing.T) {
745 got := Sprintln("<", 1, ">:", 1, 2, 3, "!")
746 expect := "< 1 >: 1 2 3 !\n"
747 if got != expect {
748 t.Errorf("got %q expected %q", got, expect)
749 }
750 }
751
752
753 func TestFormatterPrintln(t *testing.T) {
754 f := F(1)
755 expect := "<v=F(1)>\n"
756 s := Sprint(f, "\n")
757 if s != expect {
758 t.Errorf("Sprint wrong with Formatter: expected %q got %q", expect, s)
759 }
760 s = Sprintln(f)
761 if s != expect {
762 t.Errorf("Sprintln wrong with Formatter: expected %q got %q", expect, s)
763 }
764 s = Sprintf("%v\n", f)
765 if s != expect {
766 t.Errorf("Sprintf wrong with Formatter: expected %q got %q", expect, s)
767 }
768 }
769
770 func args(a ...interface{}) []interface{} { return a }
771
772 var startests = []struct {
773 fmt string
774 in []interface{}
775 out string
776 }{
777 {"%*d", args(4, 42), " 42"},
778 {"%.*d", args(4, 42), "0042"},
779 {"%*.*d", args(8, 4, 42), " 0042"},
780 {"%0*d", args(4, 42), "0042"},
781 {"%-*d", args(4, 42), "42 "},
782
783
784 {"%*d", args(nil, 42), "%!(BADWIDTH)42"},
785 {"%.*d", args(nil, 42), "%!(BADPREC)42"},
786 {"%*d", args(5, "foo"), "%!d(string= foo)"},
787 {"%*% %d", args(20, 5), "% 5"},
788 {"%*", args(4), "%!(NOVERB)"},
789 {"%*d", args(int32(4), 42), "%!(BADWIDTH)42"},
790 }
791
792 func TestWidthAndPrecision(t *testing.T) {
793 for _, tt := range startests {
794 s := Sprintf(tt.fmt, tt.in...)
795 if s != tt.out {
796 t.Errorf("%q: got %q expected %q", tt.fmt, s, tt.out)
797 }
798 }
799 }
800
801
802 type Panic struct {
803 message interface{}
804 }
805
806
807 func (p Panic) GoString() string {
808 panic(p.message)
809 }
810
811
812 func (p Panic) String() string {
813 panic(p.message)
814 }
815
816
817 type PanicF struct {
818 message interface{}
819 }
820
821
822 func (p PanicF) Format(f State, c rune) {
823 panic(p.message)
824 }
825
826 var panictests = []struct {
827 fmt string
828 in interface{}
829 out string
830 }{
831
832 {"%s", (*Panic)(nil), "<nil>"},
833 {"%s", Panic{io.ErrUnexpectedEOF}, "%s(PANIC=unexpected EOF)"},
834 {"%s", Panic{3}, "%s(PANIC=3)"},
835
836 {"%#v", (*Panic)(nil), "<nil>"},
837 {"%#v", Panic{io.ErrUnexpectedEOF}, "%v(PANIC=unexpected EOF)"},
838 {"%#v", Panic{3}, "%v(PANIC=3)"},
839
840 {"%s", (*PanicF)(nil), "<nil>"},
841 {"%s", PanicF{io.ErrUnexpectedEOF}, "%s(PANIC=unexpected EOF)"},
842 {"%s", PanicF{3}, "%s(PANIC=3)"},
843 }
844
845 func TestPanics(t *testing.T) {
846 for _, tt := range panictests {
847 s := Sprintf(tt.fmt, tt.in)
848 if s != tt.out {
849 t.Errorf("%q: got %q expected %q", tt.fmt, s, tt.out)
850 }
851 }
852 }
853
854
855 var recurCount = 0
856
857 type Recur struct {
858 i int
859 failed *bool
860 }
861
862 func (r Recur) String() string {
863 if recurCount++; recurCount > 10 {
864 *r.failed = true
865 return "FAIL"
866 }
867
868
869
870 return Sprintf("recur@%p value: %d", r, r.i)
871 }
872
873 func TestBadVerbRecursion(t *testing.T) {
874 failed := false
875 r := Recur{3, &failed}
876 Sprintf("recur@%p value: %d\n", &r, r.i)
877 if failed {
878 t.Error("fail with pointer")
879 }
880 failed = false
881 r = Recur{4, &failed}
882 Sprintf("recur@%p, value: %d\n", r, r.i)
883 if failed {
884 t.Error("fail with value")
885 }
886 }
887
888 func TestIsSpace(t *testing.T) {
889
890
891 for i := rune(0); i <= unicode.MaxRune; i++ {
892 if IsSpace(i) != unicode.IsSpace(i) {
893 t.Errorf("isSpace(%U) = %v, want %v", i, IsSpace(i), unicode.IsSpace(i))
894 }
895 }
896 }
897
898 func TestNilDoesNotBecomeTyped(t *testing.T) {
899 type A struct{}
900 type B struct{}
901 var a *A = nil
902 var b B = B{}
903 got := Sprintf("%s %s %s %s %s", nil, a, nil, b, nil)
904 const expect = "%!s(<nil>) %!s(*fmt_test.A=<nil>) %!s(<nil>) {} %!s(<nil>)"
905 if got != expect {
906 t.Errorf("expected:\n\t%q\ngot:\n\t%q", expect, got)
907 }
908 }
View as plain text