OSDN Git Service

beb410fa117fd94172a8160e0741eaacb7e64cbc
[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 var mallocTest = []struct {
512         count int
513         desc  string
514         fn    func()
515 }{
516         {0, `Sprintf("")`, func() { Sprintf("") }},
517         {1, `Sprintf("xxx")`, func() { Sprintf("xxx") }},
518         {1, `Sprintf("%x")`, func() { Sprintf("%x", 7) }},
519         {2, `Sprintf("%s")`, func() { Sprintf("%s", "hello") }},
520         {1, `Sprintf("%x %x")`, func() { Sprintf("%x %x", 7, 112) }},
521         {1, `Sprintf("%g")`, func() { Sprintf("%g", 3.14159) }},
522         {0, `Fprintf(buf, "%x %x %x")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%x %x %x", 7, 8, 9) }},
523         {1, `Fprintf(buf, "%s")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%s", "hello") }},
524 }
525
526 var _ bytes.Buffer
527
528 func TestCountMallocs(t *testing.T) {
529         if testing.Short() {
530                 return
531         }
532         for _, mt := range mallocTest {
533                 const N = 100
534                 runtime.UpdateMemStats()
535                 mallocs := 0 - runtime.MemStats.Mallocs
536                 for i := 0; i < N; i++ {
537                         mt.fn()
538                 }
539                 runtime.UpdateMemStats()
540                 mallocs += runtime.MemStats.Mallocs
541                 if mallocs/N != uint64(mt.count) {
542                         t.Errorf("%s: expected %d mallocs, got %d", mt.desc, mt.count, mallocs/N)
543                 }
544         }
545 }
546
547 type flagPrinter struct{}
548
549 func (*flagPrinter) Format(f State, c rune) {
550         s := "%"
551         for i := 0; i < 128; i++ {
552                 if f.Flag(i) {
553                         s += string(i)
554                 }
555         }
556         if w, ok := f.Width(); ok {
557                 s += Sprintf("%d", w)
558         }
559         if p, ok := f.Precision(); ok {
560                 s += Sprintf(".%d", p)
561         }
562         s += string(c)
563         io.WriteString(f, "["+s+"]")
564 }
565
566 var flagtests = []struct {
567         in  string
568         out string
569 }{
570         {"%a", "[%a]"},
571         {"%-a", "[%-a]"},
572         {"%+a", "[%+a]"},
573         {"%#a", "[%#a]"},
574         {"% a", "[% a]"},
575         {"%0a", "[%0a]"},
576         {"%1.2a", "[%1.2a]"},
577         {"%-1.2a", "[%-1.2a]"},
578         {"%+1.2a", "[%+1.2a]"},
579         {"%-+1.2a", "[%+-1.2a]"},
580         {"%-+1.2abc", "[%+-1.2a]bc"},
581         {"%-1.2abc", "[%-1.2a]bc"},
582 }
583
584 func TestFlagParser(t *testing.T) {
585         var flagprinter flagPrinter
586         for _, tt := range flagtests {
587                 s := Sprintf(tt.in, &flagprinter)
588                 if s != tt.out {
589                         t.Errorf("Sprintf(%q, &flagprinter) => %q, want %q", tt.in, s, tt.out)
590                 }
591         }
592 }
593
594 func TestStructPrinter(t *testing.T) {
595         var s struct {
596                 a string
597                 b string
598                 c int
599         }
600         s.a = "abc"
601         s.b = "def"
602         s.c = 123
603         var tests = []struct {
604                 fmt string
605                 out string
606         }{
607                 {"%v", "{abc def 123}"},
608                 {"%+v", "{a:abc b:def c:123}"},
609         }
610         for _, tt := range tests {
611                 out := Sprintf(tt.fmt, s)
612                 if out != tt.out {
613                         t.Errorf("Sprintf(%q, &s) = %q, want %q", tt.fmt, out, tt.out)
614                 }
615         }
616 }
617
618 // Check map printing using substrings so we don't depend on the print order.
619 func presentInMap(s string, a []string, t *testing.T) {
620         for i := 0; i < len(a); i++ {
621                 loc := strings.Index(s, a[i])
622                 if loc < 0 {
623                         t.Errorf("map print: expected to find %q in %q", a[i], s)
624                 }
625                 // make sure the match ends here
626                 loc += len(a[i])
627                 if loc >= len(s) || (s[loc] != ' ' && s[loc] != ']') {
628                         t.Errorf("map print: %q not properly terminated in %q", a[i], s)
629                 }
630         }
631 }
632
633 func TestMapPrinter(t *testing.T) {
634         m0 := make(map[int]string)
635         s := Sprint(m0)
636         if s != "map[]" {
637                 t.Errorf("empty map printed as %q not %q", s, "map[]")
638         }
639         m1 := map[int]string{1: "one", 2: "two", 3: "three"}
640         a := []string{"1:one", "2:two", "3:three"}
641         presentInMap(Sprintf("%v", m1), a, t)
642         presentInMap(Sprint(m1), a, t)
643 }
644
645 func TestEmptyMap(t *testing.T) {
646         const emptyMapStr = "map[]"
647         var m map[string]int
648         s := Sprint(m)
649         if s != emptyMapStr {
650                 t.Errorf("nil map printed as %q not %q", s, emptyMapStr)
651         }
652         m = make(map[string]int)
653         s = Sprint(m)
654         if s != emptyMapStr {
655                 t.Errorf("empty map printed as %q not %q", s, emptyMapStr)
656         }
657 }
658
659 // Check that Sprint (and hence Print, Fprint) puts spaces in the right places,
660 // that is, between arg pairs in which neither is a string.
661 func TestBlank(t *testing.T) {
662         got := Sprint("<", 1, ">:", 1, 2, 3, "!")
663         expect := "<1>:1 2 3!"
664         if got != expect {
665                 t.Errorf("got %q expected %q", got, expect)
666         }
667 }
668
669 // Check that Sprintln (and hence Println, Fprintln) puts spaces in the right places,
670 // that is, between all arg pairs.
671 func TestBlankln(t *testing.T) {
672         got := Sprintln("<", 1, ">:", 1, 2, 3, "!")
673         expect := "< 1 >: 1 2 3 !\n"
674         if got != expect {
675                 t.Errorf("got %q expected %q", got, expect)
676         }
677 }
678
679 // Check Formatter with Sprint, Sprintln, Sprintf
680 func TestFormatterPrintln(t *testing.T) {
681         f := F(1)
682         expect := "<v=F(1)>\n"
683         s := Sprint(f, "\n")
684         if s != expect {
685                 t.Errorf("Sprint wrong with Formatter: expected %q got %q", expect, s)
686         }
687         s = Sprintln(f)
688         if s != expect {
689                 t.Errorf("Sprintln wrong with Formatter: expected %q got %q", expect, s)
690         }
691         s = Sprintf("%v\n", f)
692         if s != expect {
693                 t.Errorf("Sprintf wrong with Formatter: expected %q got %q", expect, s)
694         }
695 }
696
697 func args(a ...interface{}) []interface{} { return a }
698
699 var startests = []struct {
700         fmt string
701         in  []interface{}
702         out string
703 }{
704         {"%*d", args(4, 42), "  42"},
705         {"%.*d", args(4, 42), "0042"},
706         {"%*.*d", args(8, 4, 42), "    0042"},
707         {"%0*d", args(4, 42), "0042"},
708         {"%-*d", args(4, 42), "42  "},
709
710         // erroneous
711         {"%*d", args(nil, 42), "%!(BADWIDTH)42"},
712         {"%.*d", args(nil, 42), "%!(BADPREC)42"},
713         {"%*d", args(5, "foo"), "%!d(string=  foo)"},
714         {"%*% %d", args(20, 5), "% 5"},
715         {"%*", args(4), "%!(NOVERB)"},
716         {"%*d", args(int32(4), 42), "%!(BADWIDTH)42"},
717 }
718
719 func TestWidthAndPrecision(t *testing.T) {
720         for _, tt := range startests {
721                 s := Sprintf(tt.fmt, tt.in...)
722                 if s != tt.out {
723                         t.Errorf("%q: got %q expected %q", tt.fmt, s, tt.out)
724                 }
725         }
726 }
727
728 // A type that panics in String.
729 type Panic struct {
730         message interface{}
731 }
732
733 // Value receiver.
734 func (p Panic) GoString() string {
735         panic(p.message)
736 }
737
738 // Value receiver.
739 func (p Panic) String() string {
740         panic(p.message)
741 }
742
743 // A type that panics in Format.
744 type PanicF struct {
745         message interface{}
746 }
747
748 // Value receiver.
749 func (p PanicF) Format(f State, c rune) {
750         panic(p.message)
751 }
752
753 var panictests = []struct {
754         fmt string
755         in  interface{}
756         out string
757 }{
758         // String
759         {"%s", (*Panic)(nil), "<nil>"}, // nil pointer special case
760         {"%s", Panic{io.ErrUnexpectedEOF}, "%s(PANIC=unexpected EOF)"},
761         {"%s", Panic{3}, "%s(PANIC=3)"},
762         // GoString
763         {"%#v", (*Panic)(nil), "<nil>"}, // nil pointer special case
764         {"%#v", Panic{io.ErrUnexpectedEOF}, "%v(PANIC=unexpected EOF)"},
765         {"%#v", Panic{3}, "%v(PANIC=3)"},
766         // Format
767         {"%s", (*PanicF)(nil), "<nil>"}, // nil pointer special case
768         {"%s", PanicF{io.ErrUnexpectedEOF}, "%s(PANIC=unexpected EOF)"},
769         {"%s", PanicF{3}, "%s(PANIC=3)"},
770 }
771
772 func TestPanics(t *testing.T) {
773         for _, tt := range panictests {
774                 s := Sprintf(tt.fmt, tt.in)
775                 if s != tt.out {
776                         t.Errorf("%q: got %q expected %q", tt.fmt, s, tt.out)
777                 }
778         }
779 }
780
781 // Test that erroneous String routine doesn't cause fatal recursion.
782 var recurCount = 0
783
784 type Recur struct {
785         i      int
786         failed *bool
787 }
788
789 func (r Recur) String() string {
790         if recurCount++; recurCount > 10 {
791                 *r.failed = true
792                 return "FAIL"
793         }
794         // This will call badVerb. Before the fix, that would cause us to recur into
795         // this routine to print %!p(value). Now we don't call the user's method
796         // during an error.
797         return Sprintf("recur@%p value: %d", r, r.i)
798 }
799
800 func TestBadVerbRecursion(t *testing.T) {
801         failed := false
802         r := Recur{3, &failed}
803         Sprintf("recur@%p value: %d\n", &r, r.i)
804         if failed {
805                 t.Error("fail with pointer")
806         }
807         failed = false
808         r = Recur{4, &failed}
809         Sprintf("recur@%p, value: %d\n", r, r.i)
810         if failed {
811                 t.Error("fail with value")
812         }
813 }