OSDN Git Service

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