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