Source file
src/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 "internal/race"
11 "io"
12 "math"
13 "reflect"
14 "strings"
15 "testing"
16 "time"
17 "unicode"
18 )
19
20 type (
21 renamedBool bool
22 renamedInt int
23 renamedInt8 int8
24 renamedInt16 int16
25 renamedInt32 int32
26 renamedInt64 int64
27 renamedUint uint
28 renamedUint8 uint8
29 renamedUint16 uint16
30 renamedUint32 uint32
31 renamedUint64 uint64
32 renamedUintptr uintptr
33 renamedString string
34 renamedBytes []byte
35 renamedFloat32 float32
36 renamedFloat64 float64
37 renamedComplex64 complex64
38 renamedComplex128 complex128
39 )
40
41 func TestFmtInterface(t *testing.T) {
42 var i1 any
43 i1 = "abc"
44 s := Sprintf("%s", i1)
45 if s != "abc" {
46 t.Errorf(`Sprintf("%%s", empty("abc")) = %q want %q`, s, "abc")
47 }
48 }
49
50 var (
51 NaN = math.NaN()
52 posInf = math.Inf(1)
53 negInf = math.Inf(-1)
54
55 intVar = 0
56
57 array = [5]int{1, 2, 3, 4, 5}
58 iarray = [4]any{1, "hello", 2.5, nil}
59 slice = array[:]
60 islice = iarray[:]
61 )
62
63 type A struct {
64 i int
65 j uint
66 s string
67 x []int
68 }
69
70 type I int
71
72 func (i I) String() string { return Sprintf("<%d>", int(i)) }
73
74 type B struct {
75 I I
76 j int
77 }
78
79 type C struct {
80 i int
81 B
82 }
83
84 type F int
85
86 func (f F) Format(s State, c rune) {
87 Fprintf(s, "<%c=F(%d)>", c, int(f))
88 }
89
90 type G int
91
92 func (g G) GoString() string {
93 return Sprintf("GoString(%d)", int(g))
94 }
95
96 type S struct {
97 F F // a struct field that Formats
98 G G // a struct field that GoStrings
99 }
100
101 type SI struct {
102 I any
103 }
104
105 // P is a type with a String method with pointer receiver for testing %p.
106 type P int
107
108 var pValue P
109
110 func (p *P) String() string {
111 return "String(p)"
112 }
113
114 // Fn is a function type with a String method.
115 type Fn func() int
116
117 func (fn Fn) String() string { return "String(fn)" }
118
119 var fnValue Fn
120
121 // U is a type with two unexported function fields.
122 type U struct {
123 u func() string
124 fn Fn
125 }
126
127 var barray = [5]renamedUint8{1, 2, 3, 4, 5}
128 var bslice = barray[:]
129
130 type byteStringer byte
131
132 func (byteStringer) String() string {
133 return "X"
134 }
135
136 var byteStringerSlice = []byteStringer{'h', 'e', 'l', 'l', 'o'}
137
138 type byteFormatter byte
139
140 func (byteFormatter) Format(f State, _ rune) {
141 Fprint(f, "X")
142 }
143
144 var byteFormatterSlice = []byteFormatter{'h', 'e', 'l', 'l', 'o'}
145
146 type writeStringFormatter string
147
148 func (sf writeStringFormatter) Format(f State, c rune) {
149 if sw, ok := f.(io.StringWriter); ok {
150 sw.WriteString("***" + string(sf) + "***")
151 }
152 }
153
154 var fmtTests = []struct {
155 fmt string
156 val any
157 out string
158 }{
159 {"%d", 12345, "12345"},
160 {"%v", 12345, "12345"},
161 {"%t", true, "true"},
162
163 // basic string
164 {"%s", "abc", "abc"},
165 {"%q", "abc", `"abc"`},
166 {"%x", "abc", "616263"},
167 {"%x", "\xff\xf0\x0f\xff", "fff00fff"},
168 {"%X", "\xff\xf0\x0f\xff", "FFF00FFF"},
169 {"%x", "", ""},
170 {"% x", "", ""},
171 {"%#x", "", ""},
172 {"%# x", "", ""},
173 {"%x", "xyz", "78797a"},
174 {"%X", "xyz", "78797A"},
175 {"% x", "xyz", "78 79 7a"},
176 {"% X", "xyz", "78 79 7A"},
177 {"%#x", "xyz", "0x78797a"},
178 {"%#X", "xyz", "0X78797A"},
179 {"%# x", "xyz", "0x78 0x79 0x7a"},
180 {"%# X", "xyz", "0X78 0X79 0X7A"},
181
182 // basic bytes
183 {"%s", []byte("abc"), "abc"},
184 {"%s", [3]byte{'a', 'b', 'c'}, "abc"},
185 {"%s", &[3]byte{'a', 'b', 'c'}, "&abc"},
186 {"%q", []byte("abc"), `"abc"`},
187 {"%x", []byte("abc"), "616263"},
188 {"%x", []byte("\xff\xf0\x0f\xff"), "fff00fff"},
189 {"%X", []byte("\xff\xf0\x0f\xff"), "FFF00FFF"},
190 {"%x", []byte(""), ""},
191 {"% x", []byte(""), ""},
192 {"%#x", []byte(""), ""},
193 {"%# x", []byte(""), ""},
194 {"%x", []byte("xyz"), "78797a"},
195 {"%X", []byte("xyz"), "78797A"},
196 {"% x", []byte("xyz"), "78 79 7a"},
197 {"% X", []byte("xyz"), "78 79 7A"},
198 {"%#x", []byte("xyz"), "0x78797a"},
199 {"%#X", []byte("xyz"), "0X78797A"},
200 {"%# x", []byte("xyz"), "0x78 0x79 0x7a"},
201 {"%# X", []byte("xyz"), "0X78 0X79 0X7A"},
202
203 // escaped strings
204 {"%q", "", `""`},
205 {"%#q", "", "``"},
206 {"%q", "\"", `"\""`},
207 {"%#q", "\"", "`\"`"},
208 {"%q", "`", `"` + "`" + `"`},
209 {"%#q", "`", `"` + "`" + `"`},
210 {"%q", "\n", `"\n"`},
211 {"%#q", "\n", `"\n"`},
212 {"%q", `\n`, `"\\n"`},
213 {"%#q", `\n`, "`\\n`"},
214 {"%q", "abc", `"abc"`},
215 {"%#q", "abc", "`abc`"},
216 {"%q", "日本語", `"日本語"`},
217 {"%+q", "日本語", `"\u65e5\u672c\u8a9e"`},
218 {"%#q", "日本語", "`日本語`"},
219 {"%#+q", "日本語", "`日本語`"},
220 {"%q", "\a\b\f\n\r\t\v\"\\", `"\a\b\f\n\r\t\v\"\\"`},
221 {"%+q", "\a\b\f\n\r\t\v\"\\", `"\a\b\f\n\r\t\v\"\\"`},
222 {"%#q", "\a\b\f\n\r\t\v\"\\", `"\a\b\f\n\r\t\v\"\\"`},
223 {"%#+q", "\a\b\f\n\r\t\v\"\\", `"\a\b\f\n\r\t\v\"\\"`},
224 {"%q", "☺", `"☺"`},
225 {"% q", "☺", `"☺"`}, // The space modifier should have no effect.
226 {"%+q", "☺", `"\u263a"`},
227 {"%#q", "☺", "`☺`"},
228 {"%#+q", "☺", "`☺`"},
229 {"%10q", "⌘", ` "⌘"`},
230 {"%+10q", "⌘", ` "\u2318"`},
231 {"%-10q", "⌘", `"⌘" `},
232 {"%+-10q", "⌘", `"\u2318" `},
233 {"%010q", "⌘", `0000000"⌘"`},
234 {"%+010q", "⌘", `00"\u2318"`},
235 {"%-010q", "⌘", `"⌘" `}, // 0 has no effect when - is present.
236 {"%+-010q", "⌘", `"\u2318" `},
237 {"%#8q", "\n", ` "\n"`},
238 {"%#+8q", "\r", ` "\r"`},
239 {"%#-8q", "\t", "` ` "},
240 {"%#+-8q", "\b", `"\b" `},
241 {"%q", "abc\xffdef", `"abc\xffdef"`},
242 {"%+q", "abc\xffdef", `"abc\xffdef"`},
243 {"%#q", "abc\xffdef", `"abc\xffdef"`},
244 {"%#+q", "abc\xffdef", `"abc\xffdef"`},
245 // Runes that are not printable.
246 {"%q", "\U0010ffff", `"\U0010ffff"`},
247 {"%+q", "\U0010ffff", `"\U0010ffff"`},
248 {"%#q", "\U0010ffff", "`�`"},
249 {"%#+q", "\U0010ffff", "`�`"},
250 // Runes that are not valid.
251 {"%q", string(rune(0x110000)), `"�"`},
252 {"%+q", string(rune(0x110000)), `"\ufffd"`},
253 {"%#q", string(rune(0x110000)), "`�`"},
254 {"%#+q", string(rune(0x110000)), "`�`"},
255
256 // characters
257 {"%c", uint('x'), "x"},
258 {"%c", 0xe4, "ä"},
259 {"%c", 0x672c, "本"},
260 {"%c", '日', "日"},
261 {"%.0c", '⌘', "⌘"}, // Specifying precision should have no effect.
262 {"%3c", '⌘', " ⌘"},
263 {"%-3c", '⌘', "⌘ "},
264 {"%c", uint64(0x100000000), "\ufffd"},
265 // Runes that are not printable.
266 {"%c", '\U00000e00', "\u0e00"},
267 {"%c", '\U0010ffff', "\U0010ffff"},
268 // Runes that are not valid.
269 {"%c", -1, "�"},
270 {"%c", 0xDC80, "�"},
271 {"%c", rune(0x110000), "�"},
272 {"%c", int64(0xFFFFFFFFF), "�"},
273 {"%c", uint64(0xFFFFFFFFF), "�"},
274
275 // escaped characters
276 {"%q", uint(0), `'\x00'`},
277 {"%+q", uint(0), `'\x00'`},
278 {"%q", '"', `'"'`},
279 {"%+q", '"', `'"'`},
280 {"%q", '\'', `'\''`},
281 {"%+q", '\'', `'\''`},
282 {"%q", '`', "'`'"},
283 {"%+q", '`', "'`'"},
284 {"%q", 'x', `'x'`},
285 {"%+q", 'x', `'x'`},
286 {"%q", 'ÿ', `'ÿ'`},
287 {"%+q", 'ÿ', `'\u00ff'`},
288 {"%q", '\n', `'\n'`},
289 {"%+q", '\n', `'\n'`},
290 {"%q", '☺', `'☺'`},
291 {"%+q", '☺', `'\u263a'`},
292 {"% q", '☺', `'☺'`}, // The space modifier should have no effect.
293 {"%.0q", '☺', `'☺'`}, // Specifying precision should have no effect.
294 {"%10q", '⌘', ` '⌘'`},
295 {"%+10q", '⌘', ` '\u2318'`},
296 {"%-10q", '⌘', `'⌘' `},
297 {"%+-10q", '⌘', `'\u2318' `},
298 {"%010q", '⌘', `0000000'⌘'`},
299 {"%+010q", '⌘', `00'\u2318'`},
300 {"%-010q", '⌘', `'⌘' `}, // 0 has no effect when - is present.
301 {"%+-010q", '⌘', `'\u2318' `},
302 // Runes that are not printable.
303 {"%q", '\U00000e00', `'\u0e00'`},
304 {"%q", '\U0010ffff', `'\U0010ffff'`},
305 // Runes that are not valid.
306 {"%q", int32(-1), `'�'`},
307 {"%q", 0xDC80, `'�'`},
308 {"%q", rune(0x110000), `'�'`},
309 {"%q", int64(0xFFFFFFFFF), `'�'`},
310 {"%q", uint64(0xFFFFFFFFF), `'�'`},
311
312 // width
313 {"%5s", "abc", " abc"},
314 {"%5s", []byte("abc"), " abc"},
315 {"%2s", "\u263a", " ☺"},
316 {"%2s", []byte("\u263a"), " ☺"},
317 {"%-5s", "abc", "abc "},
318 {"%-5s", []byte("abc"), "abc "},
319 {"%05s", "abc", "00abc"},
320 {"%05s", []byte("abc"), "00abc"},
321 {"%5s", "abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"},
322 {"%5s", []byte("abcdefghijklmnopqrstuvwxyz"), "abcdefghijklmnopqrstuvwxyz"},
323 {"%.5s", "abcdefghijklmnopqrstuvwxyz", "abcde"},
324 {"%.5s", []byte("abcdefghijklmnopqrstuvwxyz"), "abcde"},
325 {"%.0s", "日本語日本語", ""},
326 {"%.0s", []byte("日本語日本語"), ""},
327 {"%.5s", "日本語日本語", "日本語日本"},
328 {"%.5s", []byte("日本語日本語"), "日本語日本"},
329 {"%.10s", "日本語日本語", "日本語日本語"},
330 {"%.10s", []byte("日本語日本語"), "日本語日本語"},
331 {"%08q", "abc", `000"abc"`},
332 {"%08q", []byte("abc"), `000"abc"`},
333 {"%-8q", "abc", `"abc" `},
334 {"%-8q", []byte("abc"), `"abc" `},
335 {"%.5q", "abcdefghijklmnopqrstuvwxyz", `"abcde"`},
336 {"%.5q", []byte("abcdefghijklmnopqrstuvwxyz"), `"abcde"`},
337 {"%.5x", "abcdefghijklmnopqrstuvwxyz", "6162636465"},
338 {"%.5x", []byte("abcdefghijklmnopqrstuvwxyz"), "6162636465"},
339 {"%.3q", "日本語日本語", `"日本語"`},
340 {"%.3q", []byte("日本語日本語"), `"日本語"`},
341 {"%.1q", "日本語", `"日"`},
342 {"%.1q", []byte("日本語"), `"日"`},
343 {"%.1x", "日本語", "e6"},
344 {"%.1X", []byte("日本語"), "E6"},
345 {"%10.1q", "日本語日本語", ` "日"`},
346 {"%10.1q", []byte("日本語日本語"), ` "日"`},
347 {"%10v", nil, " <nil>"},
348 {"%-10v", nil, "<nil> "},
349
350 // integers
351 {"%d", uint(12345), "12345"},
352 {"%d", int(-12345), "-12345"},
353 {"%d", ^uint8(0), "255"},
354 {"%d", ^uint16(0), "65535"},
355 {"%d", ^uint32(0), "4294967295"},
356 {"%d", ^uint64(0), "18446744073709551615"},
357 {"%d", int8(-1 << 7), "-128"},
358 {"%d", int16(-1 << 15), "-32768"},
359 {"%d", int32(-1 << 31), "-2147483648"},
360 {"%d", int64(-1 << 63), "-9223372036854775808"},
361 {"%.d", 0, ""},
362 {"%.0d", 0, ""},
363 {"%6.0d", 0, " "},
364 {"%06.0d", 0, " "},
365 {"% d", 12345, " 12345"},
366 {"%+d", 12345, "+12345"},
367 {"%+d", -12345, "-12345"},
368 {"%b", 7, "111"},
369 {"%b", -6, "-110"},
370 {"%#b", 7, "0b111"},
371 {"%#b", -6, "-0b110"},
372 {"%b", ^uint32(0), "11111111111111111111111111111111"},
373 {"%b", ^uint64(0), "1111111111111111111111111111111111111111111111111111111111111111"},
374 {"%b", int64(-1 << 63), zeroFill("-1", 63, "")},
375 {"%o", 01234, "1234"},
376 {"%o", -01234, "-1234"},
377 {"%#o", 01234, "01234"},
378 {"%#o", -01234, "-01234"},
379 {"%O", 01234, "0o1234"},
380 {"%O", -01234, "-0o1234"},
381 {"%o", ^uint32(0), "37777777777"},
382 {"%o", ^uint64(0), "1777777777777777777777"},
383 {"%#X", 0, "0X0"},
384 {"%x", 0x12abcdef, "12abcdef"},
385 {"%X", 0x12abcdef, "12ABCDEF"},
386 {"%x", ^uint32(0), "ffffffff"},
387 {"%X", ^uint64(0), "FFFFFFFFFFFFFFFF"},
388 {"%.20b", 7, "00000000000000000111"},
389 {"%10d", 12345, " 12345"},
390 {"%10d", -12345, " -12345"},
391 {"%+10d", 12345, " +12345"},
392 {"%010d", 12345, "0000012345"},
393 {"%010d", -12345, "-000012345"},
394 {"%20.8d", 1234, " 00001234"},
395 {"%20.8d", -1234, " -00001234"},
396 {"%020.8d", 1234, " 00001234"},
397 {"%020.8d", -1234, " -00001234"},
398 {"%-20.8d", 1234, "00001234 "},
399 {"%-20.8d", -1234, "-00001234 "},
400 {"%-#20.8x", 0x1234abc, "0x01234abc "},
401 {"%-#20.8X", 0x1234abc, "0X01234ABC "},
402 {"%-#20.8o", 01234, "00001234 "},
403
404 // Test correct f.intbuf overflow checks.
405 {"%068d", 1, zeroFill("", 68, "1")},
406 {"%068d", -1, zeroFill("-", 67, "1")},
407 {"%#.68x", 42, zeroFill("0x", 68, "2a")},
408 {"%.68d", -42, zeroFill("-", 68, "42")},
409 {"%+.68d", 42, zeroFill("+", 68, "42")},
410 {"% .68d", 42, zeroFill(" ", 68, "42")},
411 {"% +.68d", 42, zeroFill("+", 68, "42")},
412
413 // unicode format
414 {"%U", 0, "U+0000"},
415 {"%U", -1, "U+FFFFFFFFFFFFFFFF"},
416 {"%U", '\n', `U+000A`},
417 {"%#U", '\n', `U+000A`},
418 {"%+U", 'x', `U+0078`}, // Plus flag should have no effect.
419 {"%# U", 'x', `U+0078 'x'`}, // Space flag should have no effect.
420 {"%#.2U", 'x', `U+0078 'x'`}, // Precisions below 4 should print 4 digits.
421 {"%U", '\u263a', `U+263A`},
422 {"%#U", '\u263a', `U+263A '☺'`},
423 {"%U", '\U0001D6C2', `U+1D6C2`},
424 {"%#U", '\U0001D6C2', `U+1D6C2 'α'`},
425 {"%#14.6U", '⌘', " U+002318 '⌘'"},
426 {"%#-14.6U", '⌘', "U+002318 '⌘' "},
427 {"%#014.6U", '⌘', " U+002318 '⌘'"},
428 {"%#-014.6U", '⌘', "U+002318 '⌘' "},
429 {"%.68U", uint(42), zeroFill("U+", 68, "2A")},
430 {"%#.68U", '日', zeroFill("U+", 68, "65E5") + " '日'"},
431
432 // floats
433 {"%+.3e", 0.0, "+0.000e+00"},
434 {"%+.3e", 1.0, "+1.000e+00"},
435 {"%+.3x", 0.0, "+0x0.000p+00"},
436 {"%+.3x", 1.0, "+0x1.000p+00"},
437 {"%+.3f", -1.0, "-1.000"},
438 {"%+.3F", -1.0, "-1.000"},
439 {"%+.3F", float32(-1.0), "-1.000"},
440 {"%+07.2f", 1.0, "+001.00"},
441 {"%+07.2f", -1.0, "-001.00"},
442 {"%-07.2f", 1.0, "1.00 "},
443 {"%-07.2f", -1.0, "-1.00 "},
444 {"%+-07.2f", 1.0, "+1.00 "},
445 {"%+-07.2f", -1.0, "-1.00 "},
446 {"%-+07.2f", 1.0, "+1.00 "},
447 {"%-+07.2f", -1.0, "-1.00 "},
448 {"%+10.2f", +1.0, " +1.00"},
449 {"%+10.2f", -1.0, " -1.00"},
450 {"% .3E", -1.0, "-1.000E+00"},
451 {"% .3e", 1.0, " 1.000e+00"},
452 {"% .3X", -1.0, "-0X1.000P+00"},
453 {"% .3x", 1.0, " 0x1.000p+00"},
454 {"%+.3g", 0.0, "+0"},
455 {"%+.3g", 1.0, "+1"},
456 {"%+.3g", -1.0, "-1"},
457 {"% .3g", -1.0, "-1"},
458 {"% .3g", 1.0, " 1"},
459 {"%b", float32(1.0), "8388608p-23"},
460 {"%b", 1.0, "4503599627370496p-52"},
461 // Test sharp flag used with floats.
462 {"%#g", 1e-323, "1.00000e-323"},
463 {"%#g", -1.0, "-1.00000"},
464 {"%#g", 1.1, "1.10000"},
465 {"%#g", 123456.0, "123456."},
466 {"%#g", 1234567.0, "1.234567e+06"},
467 {"%#g", 1230000.0, "1.23000e+06"},
468 {"%#g", 1000000.0, "1.00000e+06"},
469 {"%#.0f", 1.0, "1."},
470 {"%#.0e", 1.0, "1.e+00"},
471 {"%#.0x", 1.0, "0x1.p+00"},
472 {"%#.0g", 1.0, "1."},
473 {"%#.0g", 1100000.0, "1.e+06"},
474 {"%#.4f", 1.0, "1.0000"},
475 {"%#.4e", 1.0, "1.0000e+00"},
476 {"%#.4x", 1.0, "0x1.0000p+00"},
477 {"%#.4g", 1.0, "1.000"},
478 {"%#.4g", 100000.0, "1.000e+05"},
479 {"%#.4g", 1.234, "1.234"},
480 {"%#.4g", 0.1234, "0.1234"},
481 {"%#.4g", 1.23, "1.230"},
482 {"%#.4g", 0.123, "0.1230"},
483 {"%#.4g", 1.2, "1.200"},
484 {"%#.4g", 0.12, "0.1200"},
485 {"%#.4g", 10.2, "10.20"},
486 {"%#.4g", 0.0, "0.000"},
487 {"%#.4g", 0.012, "0.01200"},
488 {"%#.0f", 123.0, "123."},
489 {"%#.0e", 123.0, "1.e+02"},
490 {"%#.0x", 123.0, "0x1.p+07"},
491 {"%#.0g", 123.0, "1.e+02"},
492 {"%#.4f", 123.0, "123.0000"},
493 {"%#.4e", 123.0, "1.2300e+02"},
494 {"%#.4x", 123.0, "0x1.ec00p+06"},
495 {"%#.4g", 123.0, "123.0"},
496 {"%#.4g", 123000.0, "1.230e+05"},
497 {"%#9.4g", 1.0, " 1.000"},
498 // The sharp flag has no effect for binary float format.
499 {"%#b", 1.0, "4503599627370496p-52"},
500 // Precision has no effect for binary float format.
501 {"%.4b", float32(1.0), "8388608p-23"},
502 {"%.4b", -1.0, "-4503599627370496p-52"},
503 // Test correct f.intbuf boundary checks.
504 {"%.68f", 1.0, zeroFill("1.", 68, "")},
505 {"%.68f", -1.0, zeroFill("-1.", 68, "")},
506 // float infinites and NaNs
507 {"%f", posInf, "+Inf"},
508 {"%.1f", negInf, "-Inf"},
509 {"% f", NaN, " NaN"},
510 {"%20f", posInf, " +Inf"},
511 {"% 20F", posInf, " Inf"},
512 {"% 20e", negInf, " -Inf"},
513 {"% 20x", negInf, " -Inf"},
514 {"%+20E", negInf, " -Inf"},
515 {"%+20X", negInf, " -Inf"},
516 {"% +20g", negInf, " -Inf"},
517 {"%+-20G", posInf, "+Inf "},
518 {"%20e", NaN, " NaN"},
519 {"%20x", NaN, " NaN"},
520 {"% +20E", NaN, " +NaN"},
521 {"% +20X", NaN, " +NaN"},
522 {"% -20g", NaN, " NaN "},
523 {"%+-20G", NaN, "+NaN "},
524 // Zero padding does not apply to infinities and NaN.
525 {"%+020e", posInf, " +Inf"},
526 {"%+020x", posInf, " +Inf"},
527 {"%-020f", negInf, "-Inf "},
528 {"%-020E", NaN, "NaN "},
529 {"%-020X", NaN, "NaN "},
530
531 // complex values
532 {"%.f", 0i, "(0+0i)"},
533 {"% .f", 0i, "( 0+0i)"},
534 {"%+.f", 0i, "(+0+0i)"},
535 {"% +.f", 0i, "(+0+0i)"},
536 {"%+.3e", 0i, "(+0.000e+00+0.000e+00i)"},
537 {"%+.3x", 0i, "(+0x0.000p+00+0x0.000p+00i)"},
538 {"%+.3f", 0i, "(+0.000+0.000i)"},
539 {"%+.3g", 0i, "(+0+0i)"},
540 {"%+.3e", 1 + 2i, "(+1.000e+00+2.000e+00i)"},
541 {"%+.3x", 1 + 2i, "(+0x1.000p+00+0x1.000p+01i)"},
542 {"%+.3f", 1 + 2i, "(+1.000+2.000i)"},
543 {"%+.3g", 1 + 2i, "(+1+2i)"},
544 {"%.3e", 0i, "(0.000e+00+0.000e+00i)"},
545 {"%.3x", 0i, "(0x0.000p+00+0x0.000p+00i)"},
546 {"%.3f", 0i, "(0.000+0.000i)"},
547 {"%.3F", 0i, "(0.000+0.000i)"},
548 {"%.3F", complex64(0i), "(0.000+0.000i)"},
549 {"%.3g", 0i, "(0+0i)"},
550 {"%.3e", 1 + 2i, "(1.000e+00+2.000e+00i)"},
551 {"%.3x", 1 + 2i, "(0x1.000p+00+0x1.000p+01i)"},
552 {"%.3f", 1 + 2i, "(1.000+2.000i)"},
553 {"%.3g", 1 + 2i, "(1+2i)"},
554 {"%.3e", -1 - 2i, "(-1.000e+00-2.000e+00i)"},
555 {"%.3x", -1 - 2i, "(-0x1.000p+00-0x1.000p+01i)"},
556 {"%.3f", -1 - 2i, "(-1.000-2.000i)"},
557 {"%.3g", -1 - 2i, "(-1-2i)"},
558 {"% .3E", -1 - 2i, "(-1.000E+00-2.000E+00i)"},
559 {"% .3X", -1 - 2i, "(-0X1.000P+00-0X1.000P+01i)"},
560 {"%+.3g", 1 + 2i, "(+1+2i)"},
561 {"%+.3g", complex64(1 + 2i), "(+1+2i)"},
562 {"%#g", 1 + 2i, "(1.00000+2.00000i)"},
563 {"%#g", 123456 + 789012i, "(123456.+789012.i)"},
564 {"%#g", 1e-10i, "(0.00000+1.00000e-10i)"},
565 {"%#g", -1e10 - 1.11e100i, "(-1.00000e+10-1.11000e+100i)"},
566 {"%#.0f", 1.23 + 1.0i, "(1.+1.i)"},
567 {"%#.0e", 1.23 + 1.0i, "(1.e+00+1.e+00i)"},
568 {"%#.0x", 1.23 + 1.0i, "(0x1.p+00+0x1.p+00i)"},
569 {"%#.0g", 1.23 + 1.0i, "(1.+1.i)"},
570 {"%#.0g", 0 + 100000i, "(0.+1.e+05i)"},
571 {"%#.0g", 1230000 + 0i, "(1.e+06+0.i)"},
572 {"%#.4f", 1 + 1.23i, "(1.0000+1.2300i)"},
573 {"%#.4e", 123 + 1i, "(1.2300e+02+1.0000e+00i)"},
574 {"%#.4x", 123 + 1i, "(0x1.ec00p+06+0x1.0000p+00i)"},
575 {"%#.4g", 123 + 1.23i, "(123.0+1.230i)"},
576 {"%#12.5g", 0 + 100000i, "( 0.0000 +1.0000e+05i)"},
577 {"%#12.5g", 1230000 - 0i, "( 1.2300e+06 +0.0000i)"},
578 {"%b", 1 + 2i, "(4503599627370496p-52+4503599627370496p-51i)"},
579 {"%b", complex64(1 + 2i), "(8388608p-23+8388608p-22i)"},
580 // The sharp flag has no effect for binary complex format.
581 {"%#b", 1 + 2i, "(4503599627370496p-52+4503599627370496p-51i)"},
582 // Precision has no effect for binary complex format.
583 {"%.4b", 1 + 2i, "(4503599627370496p-52+4503599627370496p-51i)"},
584 {"%.4b", complex64(1 + 2i), "(8388608p-23+8388608p-22i)"},
585 // complex infinites and NaNs
586 {"%f", complex(posInf, posInf), "(+Inf+Infi)"},
587 {"%f", complex(negInf, negInf), "(-Inf-Infi)"},
588 {"%f", complex(NaN, NaN), "(NaN+NaNi)"},
589 {"%.1f", complex(posInf, posInf), "(+Inf+Infi)"},
590 {"% f", complex(posInf, posInf), "( Inf+Infi)"},
591 {"% f", complex(negInf, negInf), "(-Inf-Infi)"},
592 {"% f", complex(NaN, NaN), "( NaN+NaNi)"},
593 {"%8e", complex(posInf, posInf), "( +Inf +Infi)"},
594 {"%8x", complex(posInf, posInf), "( +Inf +Infi)"},
595 {"% 8E", complex(posInf, posInf), "( Inf +Infi)"},
596 {"% 8X", complex(posInf, posInf), "( Inf +Infi)"},
597 {"%+8f", complex(negInf, negInf), "( -Inf -Infi)"},
598 {"% +8g", complex(negInf, negInf), "( -Inf -Infi)"},
599 {"% -8G", complex(NaN, NaN), "( NaN +NaN i)"},
600 {"%+-8b", complex(NaN, NaN), "(+NaN +NaN i)"},
601 // Zero padding does not apply to infinities and NaN.
602 {"%08f", complex(posInf, posInf), "( +Inf +Infi)"},
603 {"%-08g", complex(negInf, negInf), "(-Inf -Inf i)"},
604 {"%-08G", complex(NaN, NaN), "(NaN +NaN i)"},
605
606 // old test/fmt_test.go
607 {"%e", 1.0, "1.000000e+00"},
608 {"%e", 1234.5678e3, "1.234568e+06"},
609 {"%e", 1234.5678e-8, "1.234568e-05"},
610 {"%e", -7.0, "-7.000000e+00"},
611 {"%e", -1e-9, "-1.000000e-09"},
612 {"%f", 1234.5678e3, "1234567.800000"},
613 {"%f", 1234.5678e-8, "0.000012"},
614 {"%f", -7.0, "-7.000000"},
615 {"%f", -1e-9, "-0.000000"},
616 {"%g", 1234.5678e3, "1.2345678e+06"},
617 {"%g", float32(1234.5678e3), "1.2345678e+06"},
618 {"%g", 1234.5678e-8, "1.2345678e-05"},
619 {"%g", -7.0, "-7"},
620 {"%g", -1e-9, "-1e-09"},
621 {"%g", float32(-1e-9), "-1e-09"},
622 {"%E", 1.0, "1.000000E+00"},
623 {"%E", 1234.5678e3, "1.234568E+06"},
624 {"%E", 1234.5678e-8, "1.234568E-05"},
625 {"%E", -7.0, "-7.000000E+00"},
626 {"%E", -1e-9, "-1.000000E-09"},
627 {"%G", 1234.5678e3, "1.2345678E+06"},
628 {"%G", float32(1234.5678e3), "1.2345678E+06"},
629 {"%G", 1234.5678e-8, "1.2345678E-05"},
630 {"%G", -7.0, "-7"},
631 {"%G", -1e-9, "-1E-09"},
632 {"%G", float32(-1e-9), "-1E-09"},
633 {"%20.5s", "qwertyuiop", " qwert"},
634 {"%.5s", "qwertyuiop", "qwert"},
635 {"%-20.5s", "qwertyuiop", "qwert "},
636 {"%20c", 'x', " x"},
637 {"%-20c", 'x', "x "},
638 {"%20.6e", 1.2345e3, " 1.234500e+03"},
639 {"%20.6e", 1.2345e-3, " 1.234500e-03"},
640 {"%20e", 1.2345e3, " 1.234500e+03"},
641 {"%20e", 1.2345e-3, " 1.234500e-03"},
642 {"%20.8e", 1.2345e3, " 1.23450000e+03"},
643 {"%20f", 1.23456789e3, " 1234.567890"},
644 {"%20f", 1.23456789e-3, " 0.001235"},
645 {"%20f", 12345678901.23456789, " 12345678901.234568"},
646 {"%-20f", 1.23456789e3, "1234.567890 "},
647 {"%20.8f", 1.23456789e3, " 1234.56789000"},
648 {"%20.8f", 1.23456789e-3, " 0.00123457"},
649 {"%g", 1.23456789e3, "1234.56789"},
650 {"%g", 1.23456789e-3, "0.00123456789"},
651 {"%g", 1.23456789e20, "1.23456789e+20"},
652
653 // arrays
654 {"%v", array, "[1 2 3 4 5]"},
655 {"%v", iarray, "[1 hello 2.5 <nil>]"},
656 {"%v", barray, "[1 2 3 4 5]"},
657 {"%v", &array, "&[1 2 3 4 5]"},
658 {"%v", &iarray, "&[1 hello 2.5 <nil>]"},
659 {"%v", &barray, "&[1 2 3 4 5]"},
660
661 // slices
662 {"%v", slice, "[1 2 3 4 5]"},
663 {"%v", islice, "[1 hello 2.5 <nil>]"},
664 {"%v", bslice, "[1 2 3 4 5]"},
665 {"%v", &slice, "&[1 2 3 4 5]"},
666 {"%v", &islice, "&[1 hello 2.5 <nil>]"},
667 {"%v", &bslice, "&[1 2 3 4 5]"},
668
669 // byte arrays and slices with %b,%c,%d,%o,%U and %v
670 {"%b", [3]byte{65, 66, 67}, "[1000001 1000010 1000011]"},
671 {"%c", [3]byte{65, 66, 67}, "[A B C]"},
672 {"%d", [3]byte{65, 66, 67}, "[65 66 67]"},
673 {"%o", [3]byte{65, 66, 67}, "[101 102 103]"},
674 {"%U", [3]byte{65, 66, 67}, "[U+0041 U+0042 U+0043]"},
675 {"%v", [3]byte{65, 66, 67}, "[65 66 67]"},
676 {"%v", [1]byte{123}, "[123]"},
677 {"%012v", []byte{}, "[]"},
678 {"%#012v", []byte{}, "[]byte{}"},
679 {"%6v", []byte{1, 11, 111}, "[ 1 11 111]"},
680 {"%06v", []byte{1, 11, 111}, "[000001 000011 000111]"},
681 {"%-6v", []byte{1, 11, 111}, "[1 11 111 ]"},
682 {"%-06v", []byte{1, 11, 111}, "[1 11 111 ]"},
683 {"%#v", []byte{1, 11, 111}, "[]byte{0x1, 0xb, 0x6f}"},
684 {"%#6v", []byte{1, 11, 111}, "[]byte{ 0x1, 0xb, 0x6f}"},
685 {"%#06v", []byte{1, 11, 111}, "[]byte{0x000001, 0x00000b, 0x00006f}"},
686 {"%#-6v", []byte{1, 11, 111}, "[]byte{0x1 , 0xb , 0x6f }"},
687 {"%#-06v", []byte{1, 11, 111}, "[]byte{0x1 , 0xb , 0x6f }"},
688 // f.space should and f.plus should not have an effect with %v.
689 {"% v", []byte{1, 11, 111}, "[ 1 11 111]"},
690 {"%+v", [3]byte{1, 11, 111}, "[1 11 111]"},
691 {"%# -6v", []byte{1, 11, 111}, "[]byte{ 0x1 , 0xb , 0x6f }"},
692 {"%#+-6v", [3]byte{1, 11, 111}, "[3]uint8{0x1 , 0xb , 0x6f }"},
693 // f.space and f.plus should have an effect with %d.
694 {"% d", []byte{1, 11, 111}, "[ 1 11 111]"},
695 {"%+d", [3]byte{1, 11, 111}, "[+1 +11 +111]"},
696 {"%# -6d", []byte{1, 11, 111}, "[ 1 11 111 ]"},
697 {"%#+-6d", [3]byte{1, 11, 111}, "[+1 +11 +111 ]"},
698
699 // floates with %v
700 {"%v", 1.2345678, "1.2345678"},
701 {"%v", float32(1.2345678), "1.2345678"},
702
703 // complexes with %v
704 {"%v", 1 + 2i, "(1+2i)"},
705 {"%v", complex64(1 + 2i), "(1+2i)"},
706
707 // structs
708 {"%v", A{1, 2, "a", []int{1, 2}}, `{1 2 a [1 2]}`},
709 {"%+v", A{1, 2, "a", []int{1, 2}}, `{i:1 j:2 s:a x:[1 2]}`},
710
711 // +v on structs with Stringable items
712 {"%+v", B{1, 2}, `{I:<1> j:2}`},
713 {"%+v", C{1, B{2, 3}}, `{i:1 B:{I:<2> j:3}}`},
714
715 // other formats on Stringable items
716 {"%s", I(23), `<23>`},
717 {"%q", I(23), `"<23>"`},
718 {"%x", I(23), `3c32333e`},
719 {"%#x", I(23), `0x3c32333e`},
720 {"%# x", I(23), `0x3c 0x32 0x33 0x3e`},
721 // Stringer applies only to string formats.
722 {"%d", I(23), `23`},
723 // Stringer applies to the extracted value.
724 {"%s", reflect.ValueOf(I(23)), `<23>`},
725
726 // go syntax
727 {"%#v", A{1, 2, "a", []int{1, 2}}, `fmt_test.A{i:1, j:0x2, s:"a", x:[]int{1, 2}}`},
728 {"%#v", new(byte), "(*uint8)(0xPTR)"},
729 {"%#v", make(chan int), "(chan int)(0xPTR)"},
730 {"%#v", uint64(1<<64 - 1), "0xffffffffffffffff"},
731 {"%#v", 1000000000, "1000000000"},
732 {"%#v", map[string]int{"a": 1}, `map[string]int{"a":1}`},
733 {"%#v", map[string]B{"a": {1, 2}}, `map[string]fmt_test.B{"a":fmt_test.B{I:1, j:2}}`},
734 {"%#v", []string{"a", "b"}, `[]string{"a", "b"}`},
735 {"%#v", SI{}, `fmt_test.SI{I:interface {}(nil)}`},
736 {"%#v", []int(nil), `[]int(nil)`},
737 {"%#v", []int{}, `[]int{}`},
738 {"%#v", array, `[5]int{1, 2, 3, 4, 5}`},
739 {"%#v", &array, `&[5]int{1, 2, 3, 4, 5}`},
740 {"%#v", iarray, `[4]interface {}{1, "hello", 2.5, interface {}(nil)}`},
741 {"%#v", &iarray, `&[4]interface {}{1, "hello", 2.5, interface {}(nil)}`},
742 {"%#v", map[int]byte(nil), `map[int]uint8(nil)`},
743 {"%#v", map[int]byte{}, `map[int]uint8{}`},
744 {"%#v", "foo", `"foo"`},
745 {"%#v", barray, `[5]fmt_test.renamedUint8{0x1, 0x2, 0x3, 0x4, 0x5}`},
746 {"%#v", bslice, `[]fmt_test.renamedUint8{0x1, 0x2, 0x3, 0x4, 0x5}`},
747 {"%#v", []int32(nil), "[]int32(nil)"},
748 {"%#v", 1.2345678, "1.2345678"},
749 {"%#v", float32(1.2345678), "1.2345678"},
750
751 // functions
752 {"%v", TestFmtInterface, "0xPTR"}, // simple function
753 {"%v", reflect.ValueOf(TestFmtInterface), "0xPTR"},
754 {"%v", G.GoString, "0xPTR"}, // method expression
755 {"%v", reflect.ValueOf(G.GoString), "0xPTR"},
756 {"%v", G(23).GoString, "0xPTR"}, // method value
757 {"%v", reflect.ValueOf(G(23).GoString), "0xPTR"},
758 {"%v", reflect.ValueOf(G(23)).Method(0), "0xPTR"},
759 {"%v", Fn.String, "0xPTR"}, // method of function type
760 {"%v", reflect.ValueOf(Fn.String), "0xPTR"},
761 {"%v", fnValue, "String(fn)"}, // variable of function type with String method
762 {"%v", reflect.ValueOf(fnValue), "String(fn)"},
763 {"%v", [1]Fn{fnValue}, "[String(fn)]"}, // array of function type with String method
764 {"%v", reflect.ValueOf([1]Fn{fnValue}), "[String(fn)]"},
765 {"%v", fnValue.String, "0xPTR"}, // method value from function type
766 {"%v", reflect.ValueOf(fnValue.String), "0xPTR"},
767 {"%v", reflect.ValueOf(fnValue).Method(0), "0xPTR"},
768 {"%v", U{}.u, "<nil>"}, // unexported function field
769 {"%v", reflect.ValueOf(U{}.u), "<nil>"},
770 {"%v", reflect.ValueOf(U{}).Field(0), "<nil>"},
771 {"%v", U{fn: fnValue}.fn, "String(fn)"}, // unexported field of function type with String method
772 {"%v", reflect.ValueOf(U{fn: fnValue}.fn), "String(fn)"},
773 {"%v", reflect.ValueOf(U{fn: fnValue}).Field(1), "<nil>"},
774
775 // functions with go syntax
776 {"%#v", TestFmtInterface, "(func(*testing.T))(0xPTR)"}, // simple function
777 {"%#v", reflect.ValueOf(TestFmtInterface), "(func(*testing.T))(0xPTR)"},
778 {"%#v", G.GoString, "(func(fmt_test.G) string)(0xPTR)"}, // method expression
779 {"%#v", reflect.ValueOf(G.GoString), "(func(fmt_test.G) string)(0xPTR)"},
780 {"%#v", G(23).GoString, "(func() string)(0xPTR)"}, // method value
781 {"%#v", reflect.ValueOf(G(23).GoString), "(func() string)(0xPTR)"},
782 {"%#v", reflect.ValueOf(G(23)).Method(0), "(func() string)(0xPTR)"},
783 {"%#v", Fn.String, "(func(fmt_test.Fn) string)(0xPTR)"}, // method of function type
784 {"%#v", reflect.ValueOf(Fn.String), "(func(fmt_test.Fn) string)(0xPTR)"},
785 {"%#v", fnValue, "(fmt_test.Fn)(nil)"}, // variable of function type with String method
786 {"%#v", reflect.ValueOf(fnValue), "(fmt_test.Fn)(nil)"},
787 {"%#v", [1]Fn{fnValue}, "[1]fmt_test.Fn{(fmt_test.Fn)(nil)}"}, // array of function type with String method
788 {"%#v", reflect.ValueOf([1]Fn{fnValue}), "[1]fmt_test.Fn{(fmt_test.Fn)(nil)}"},
789 {"%#v", fnValue.String, "(func() string)(0xPTR)"}, // method value from function type
790 {"%#v", reflect.ValueOf(fnValue.String), "(func() string)(0xPTR)"},
791 {"%#v", reflect.ValueOf(fnValue).Method(0), "(func() string)(0xPTR)"},
792 {"%#v", U{}.u, "(func() string)(nil)"}, // unexported function field
793 {"%#v", reflect.ValueOf(U{}.u), "(func() string)(nil)"},
794 {"%#v", reflect.ValueOf(U{}).Field(0), "(func() string)(nil)"},
795 {"%#v", U{fn: fnValue}.fn, "(fmt_test.Fn)(nil)"}, // unexported field of function type with String method
796 {"%#v", reflect.ValueOf(U{fn: fnValue}.fn), "(fmt_test.Fn)(nil)"},
797 {"%#v", reflect.ValueOf(U{fn: fnValue}).Field(1), "(fmt_test.Fn)(nil)"},
798
799 // Whole number floats are printed without decimals. See Issue 27634.
800 {"%#v", 1.0, "1"},
801 {"%#v", 1000000.0, "1e+06"},
802 {"%#v", float32(1.0), "1"},
803 {"%#v", float32(1000000.0), "1e+06"},
804
805 // Only print []byte and []uint8 as type []byte if they appear at the top level.
806 {"%#v", []byte(nil), "[]byte(nil)"},
807 {"%#v", []uint8(nil), "[]byte(nil)"},
808 {"%#v", []byte{}, "[]byte{}"},
809 {"%#v", []uint8{}, "[]byte{}"},
810 {"%#v", reflect.ValueOf([]byte{}), "[]uint8{}"},
811 {"%#v", reflect.ValueOf([]uint8{}), "[]uint8{}"},
812 {"%#v", &[]byte{}, "&[]uint8{}"},
813 {"%#v", &[]byte{}, "&[]uint8{}"},
814 {"%#v", [3]byte{}, "[3]uint8{0x0, 0x0, 0x0}"},
815 {"%#v", [3]uint8{}, "[3]uint8{0x0, 0x0, 0x0}"},
816
817 // slices with other formats
818 {"%#x", []int{1, 2, 15}, `[0x1 0x2 0xf]`},
819 {"%x", []int{1, 2, 15}, `[1 2 f]`},
820 {"%d", []int{1, 2, 15}, `[1 2 15]`},
821 {"%d", []byte{1, 2, 15}, `[1 2 15]`},
822 {"%q", []string{"a", "b"}, `["a" "b"]`},
823 {"% 02x", []byte{1}, "01"},
824 {"% 02x", []byte{1, 2, 3}, "01 02 03"},
825
826 // Padding with byte slices.
827 {"%2x", []byte{}, " "},
828 {"%#2x", []byte{}, " "},
829 {"% 02x", []byte{}, "00"},
830 {"%# 02x", []byte{}, "00"},
831 {"%-2x", []byte{}, " "},
832 {"%-02x", []byte{}, " "},
833 {"%8x", []byte{0xab}, " ab"},
834 {"% 8x", []byte{0xab}, " ab"},
835 {"%#8x", []byte{0xab}, " 0xab"},
836 {"%# 8x", []byte{0xab}, " 0xab"},
837 {"%08x", []byte{0xab}, "000000ab"},
838 {"% 08x", []byte{0xab}, "000000ab"},
839 {"%#08x", []byte{0xab}, "00000xab"},
840 {"%# 08x", []byte{0xab}, "00000xab"},
841 {"%10x", []byte{0xab, 0xcd}, " abcd"},
842 {"% 10x", []byte{0xab, 0xcd}, " ab cd"},
843 {"%#10x", []byte{0xab, 0xcd}, " 0xabcd"},
844 {"%# 10x", []byte{0xab, 0xcd}, " 0xab 0xcd"},
845 {"%010x", []byte{0xab, 0xcd}, "000000abcd"},
846 {"% 010x", []byte{0xab, 0xcd}, "00000ab cd"},
847 {"%#010x", []byte{0xab, 0xcd}, "00000xabcd"},
848 {"%# 010x", []byte{0xab, 0xcd}, "00xab 0xcd"},
849 {"%-10X", []byte{0xab}, "AB "},
850 {"% -010X", []byte{0xab}, "AB "},
851 {"%#-10X", []byte{0xab, 0xcd}, "0XABCD "},
852 {"%# -010X", []byte{0xab, 0xcd}, "0XAB 0XCD "},
853 // Same for strings
854 {"%2x", "", " "},
855 {"%#2x", "", " "},
856 {"% 02x", "", "00"},
857 {"%# 02x", "", "00"},
858 {"%-2x", "", " "},
859 {"%-02x", "", " "},
860 {"%8x", "\xab", " ab"},
861 {"% 8x", "\xab", " ab"},
862 {"%#8x", "\xab", " 0xab"},
863 {"%# 8x", "\xab", " 0xab"},
864 {"%08x", "\xab", "000000ab"},
865 {"% 08x", "\xab", "000000ab"},
866 {"%#08x", "\xab", "00000xab"},
867 {"%# 08x", "\xab", "00000xab"},
868 {"%10x", "\xab\xcd", " abcd"},
869 {"% 10x", "\xab\xcd", " ab cd"},
870 {"%#10x", "\xab\xcd", " 0xabcd"},
871 {"%# 10x", "\xab\xcd", " 0xab 0xcd"},
872 {"%010x", "\xab\xcd", "000000abcd"},
873 {"% 010x", "\xab\xcd", "00000ab cd"},
874 {"%#010x", "\xab\xcd", "00000xabcd"},
875 {"%# 010x", "\xab\xcd", "00xab 0xcd"},
876 {"%-10X", "\xab", "AB "},
877 {"% -010X", "\xab", "AB "},
878 {"%#-10X", "\xab\xcd", "0XABCD "},
879 {"%# -010X", "\xab\xcd", "0XAB 0XCD "},
880
881 // renamings
882 {"%v", renamedBool(true), "true"},
883 {"%d", renamedBool(true), "%!d(fmt_test.renamedBool=true)"},
884 {"%o", renamedInt(8), "10"},
885 {"%d", renamedInt8(-9), "-9"},
886 {"%v", renamedInt16(10), "10"},
887 {"%v", renamedInt32(-11), "-11"},
888 {"%X", renamedInt64(255), "FF"},
889 {"%v", renamedUint(13), "13"},
890 {"%o", renamedUint8(14), "16"},
891 {"%X", renamedUint16(15), "F"},
892 {"%d", renamedUint32(16), "16"},
893 {"%X", renamedUint64(17), "11"},
894 {"%o", renamedUintptr(18), "22"},
895 {"%x", renamedString("thing"), "7468696e67"},
896 {"%d", renamedBytes([]byte{1, 2, 15}), `[1 2 15]`},
897 {"%q", renamedBytes([]byte("hello")), `"hello"`},
898 {"%x", []renamedUint8{'h', 'e', 'l', 'l', 'o'}, "68656c6c6f"},
899 {"%X", []renamedUint8{'h', 'e', 'l', 'l', 'o'}, "68656C6C6F"},
900 {"%s", []renamedUint8{'h', 'e', 'l', 'l', 'o'}, "hello"},
901 {"%q", []renamedUint8{'h', 'e', 'l', 'l', 'o'}, `"hello"`},
902 {"%v", renamedFloat32(22), "22"},
903 {"%v", renamedFloat64(33), "33"},
904 {"%v", renamedComplex64(3 + 4i), "(3+4i)"},
905 {"%v", renamedComplex128(4 - 3i), "(4-3i)"},
906
907 // Formatter
908 {"%x", F(1), "<x=F(1)>"},
909 {"%x", G(2), "2"},
910 {"%+v", S{F(4), G(5)}, "{F:<v=F(4)> G:5}"},
911
912 // GoStringer
913 {"%#v", G(6), "GoString(6)"},
914 {"%#v", S{F(7), G(8)}, "fmt_test.S{F:<v=F(7)>, G:GoString(8)}"},
915
916 // %T
917 {"%T", byte(0), "uint8"},
918 {"%T", reflect.ValueOf(nil), "reflect.Value"},
919 {"%T", (4 - 3i), "complex128"},
920 {"%T", renamedComplex128(4 - 3i), "fmt_test.renamedComplex128"},
921 {"%T", intVar, "int"},
922 {"%6T", &intVar, " *int"},
923 {"%10T", nil, " <nil>"},
924 {"%-10T", nil, "<nil> "},
925
926 // %p with pointers
927 {"%p", (*int)(nil), "0x0"},
928 {"%#p", (*int)(nil), "0"},
929 {"%p", &intVar, "0xPTR"},
930 {"%#p", &intVar, "PTR"},
931 {"%p", &array, "0xPTR"},
932 {"%p", &slice, "0xPTR"},
933 {"%8.2p", (*int)(nil), " 0x00"},
934 {"%-20.16p", &intVar, "0xPTR "},
935 // %p on non-pointers
936 {"%p", make(chan int), "0xPTR"},
937 {"%p", make(map[int]int), "0xPTR"},
938 {"%p", func() {}, "0xPTR"},
939 {"%p", 27, "%!p(int=27)"}, // not a pointer at all
940 {"%p", nil, "%!p(<nil>)"}, // nil on its own has no type ...
941 {"%#p", nil, "%!p(<nil>)"}, // ... and hence is not a pointer type.
942 // pointers with specified base
943 {"%b", &intVar, "PTR_b"},
944 {"%d", &intVar, "PTR_d"},
945 {"%o", &intVar, "PTR_o"},
946 {"%x", &intVar, "PTR_x"},
947 {"%X", &intVar, "PTR_X"},
948 // %v on pointers
949 {"%v", nil, "<nil>"},
950 {"%#v", nil, "<nil>"},
951 {"%v", (*int)(nil), "<nil>"},
952 {"%#v", (*int)(nil), "(*int)(nil)"},
953 {"%v", &intVar, "0xPTR"},
954 {"%#v", &intVar, "(*int)(0xPTR)"},
955 {"%8.2v", (*int)(nil), " <nil>"},
956 {"%-20.16v", &intVar, "0xPTR "},
957 // string method on pointer
958 {"%s", &pValue, "String(p)"}, // String method...
959 {"%p", &pValue, "0xPTR"}, // ... is not called with %p.
960
961 // %d on Stringer should give integer if possible
962 {"%s", time.Time{}.Month(), "January"},
963 {"%d", time.Time{}.Month(), "1"},
964
965 // erroneous things
966 {"", nil, "%!(EXTRA <nil>)"},
967 {"", 2, "%!(EXTRA int=2)"},
968 {"no args", "hello", "no args%!(EXTRA string=hello)"},
969 {"%s %", "hello", "hello %!(NOVERB)"},
970 {"%s %.2", "hello", "hello %!(NOVERB)"},
971 {"%017091901790959340919092959340919017929593813360", 0, "%!(NOVERB)%!(EXTRA int=0)"},
972 {"%184467440737095516170v", 0, "%!(NOVERB)%!(EXTRA int=0)"},
973 // Extra argument errors should format without flags set.
974 {"%010.2", "12345", "%!(NOVERB)%!(EXTRA string=12345)"},
975
976 // Test that maps with non-reflexive keys print all keys and values.
977 {"%v", map[float64]int{NaN: 1, NaN: 1}, "map[NaN:1 NaN:1]"},
978
979 // Comparison of padding rules with C printf.
980 /*
981 C program:
982 #include <stdio.h>
983
984 char *format[] = {
985 "[%.2f]",
986 "[% .2f]",
987 "[%+.2f]",
988 "[%7.2f]",
989 "[% 7.2f]",
990 "[%+7.2f]",
991 "[% +7.2f]",
992 "[%07.2f]",
993 "[% 07.2f]",
994 "[%+07.2f]",
995 "[% +07.2f]"
996 };
997
998 int main(void) {
999 int i;
1000 for(i = 0; i < 11; i++) {
1001 printf("%s: ", format[i]);
1002 printf(format[i], 1.0);
1003 printf(" ");
1004 printf(format[i], -1.0);
1005 printf("\n");
1006 }
1007 }
1008
1009 Output:
1010 [%.2f]: [1.00] [-1.00]
1011 [% .2f]: [ 1.00] [-1.00]
1012 [%+.2f]: [+1.00] [-1.00]
1013 [%7.2f]: [ 1.00] [ -1.00]
1014 [% 7.2f]: [ 1.00] [ -1.00]
1015 [%+7.2f]: [ +1.00] [ -1.00]
1016 [% +7.2f]: [ +1.00] [ -1.00]
1017 [%07.2f]: [0001.00] [-001.00]
1018 [% 07.2f]: [ 001.00] [-001.00]
1019 [%+07.2f]: [+001.00] [-001.00]
1020 [% +07.2f]: [+001.00] [-001.00]
1021
1022 */
1023 {"%.2f", 1.0, "1.00"},
1024 {"%.2f", -1.0, "-1.00"},
1025 {"% .2f", 1.0, " 1.00"},
1026 {"% .2f", -1.0, "-1.00"},
1027 {"%+.2f", 1.0, "+1.00"},
1028 {"%+.2f", -1.0, "-1.00"},
1029 {"%7.2f", 1.0, " 1.00"},
1030 {"%7.2f", -1.0, " -1.00"},
1031 {"% 7.2f", 1.0, " 1.00"},
1032 {"% 7.2f", -1.0, " -1.00"},
1033 {"%+7.2f", 1.0, " +1.00"},
1034 {"%+7.2f", -1.0, " -1.00"},
1035 {"% +7.2f", 1.0, " +1.00"},
1036 {"% +7.2f", -1.0, " -1.00"},
1037 {"%07.2f", 1.0, "0001.00"},
1038 {"%07.2f", -1.0, "-001.00"},
1039 {"% 07.2f", 1.0, " 001.00"},
1040 {"% 07.2f", -1.0, "-001.00"},
1041 {"%+07.2f", 1.0, "+001.00"},
1042 {"%+07.2f", -1.0, "-001.00"},
1043 {"% +07.2f", 1.0, "+001.00"},
1044 {"% +07.2f", -1.0, "-001.00"},
1045
1046 // Complex numbers: exhaustively tested in TestComplexFormatting.
1047 {"%7.2f", 1 + 2i, "( 1.00 +2.00i)"},
1048 {"%+07.2f", -1 - 2i, "(-001.00-002.00i)"},
1049
1050 // Use spaces instead of zero if padding to the right.
1051 {"%0-5s", "abc", "abc "},
1052 {"%-05.1f", 1.0, "1.0 "},
1053
1054 // float and complex formatting should not change the padding width
1055 // for other elements. See issue 14642.
1056 {"%06v", []any{+10.0, 10}, "[000010 000010]"},
1057 {"%06v", []any{-10.0, 10}, "[-00010 000010]"},
1058 {"%06v", []any{+10.0 + 10i, 10}, "[(000010+00010i) 000010]"},
1059 {"%06v", []any{-10.0 + 10i, 10}, "[(-00010+00010i) 000010]"},
1060
1061 // integer formatting should not alter padding for other elements.
1062 {"%03.6v", []any{1, 2.0, "x"}, "[000001 002 00x]"},
1063 {"%03.0v", []any{0, 2.0, "x"}, "[ 002 000]"},
1064
1065 // Complex fmt used to leave the plus flag set for future entries in the array
1066 // causing +2+0i and +3+0i instead of 2+0i and 3+0i.
1067 {"%v", []complex64{1, 2, 3}, "[(1+0i) (2+0i) (3+0i)]"},
1068 {"%v", []complex128{1, 2, 3}, "[(1+0i) (2+0i) (3+0i)]"},
1069
1070 // Incomplete format specification caused crash.
1071 {"%.", 3, "%!.(int=3)"},
1072
1073 // Padding for complex numbers. Has been bad, then fixed, then bad again.
1074 {"%+10.2f", +104.66 + 440.51i, "( +104.66 +440.51i)"},
1075 {"%+10.2f", -104.66 + 440.51i, "( -104.66 +440.51i)"},
1076 {"%+10.2f", +104.66 - 440.51i, "( +104.66 -440.51i)"},
1077 {"%+10.2f", -104.66 - 440.51i, "( -104.66 -440.51i)"},
1078 {"%+010.2f", +104.66 + 440.51i, "(+000104.66+000440.51i)"},
1079 {"%+010.2f", -104.66 + 440.51i, "(-000104.66+000440.51i)"},
1080 {"%+010.2f", +104.66 - 440.51i, "(+000104.66-000440.51i)"},
1081 {"%+010.2f", -104.66 - 440.51i, "(-000104.66-000440.51i)"},
1082
1083 // []T where type T is a byte with a Stringer method.
1084 {"%v", byteStringerSlice, "[X X X X X]"},
1085 {"%s", byteStringerSlice, "hello"},
1086 {"%q", byteStringerSlice, "\"hello\""},
1087 {"%x", byteStringerSlice, "68656c6c6f"},
1088 {"%X", byteStringerSlice, "68656C6C6F"},
1089 {"%#v", byteStringerSlice, "[]fmt_test.byteStringer{0x68, 0x65, 0x6c, 0x6c, 0x6f}"},
1090
1091 // And the same for Formatter.
1092 {"%v", byteFormatterSlice, "[X X X X X]"},
1093 {"%s", byteFormatterSlice, "hello"},
1094 {"%q", byteFormatterSlice, "\"hello\""},
1095 {"%x", byteFormatterSlice, "68656c6c6f"},
1096 {"%X", byteFormatterSlice, "68656C6C6F"},
1097 // This next case seems wrong, but the docs say the Formatter wins here.
1098 {"%#v", byteFormatterSlice, "[]fmt_test.byteFormatter{X, X, X, X, X}"},
1099
1100 // pp.WriteString
1101 {"%s", writeStringFormatter(""), "******"},
1102 {"%s", writeStringFormatter("xyz"), "***xyz***"},
1103 {"%s", writeStringFormatter("⌘/⌘"), "***⌘/⌘***"},
1104
1105 // reflect.Value handled specially in Go 1.5, making it possible to
1106 // see inside non-exported fields (which cannot be accessed with Interface()).
1107 // Issue 8965.
1108 {"%v", reflect.ValueOf(A{}).Field(0).String(), "<int Value>"}, // Equivalent to the old way.
1109 {"%v", reflect.ValueOf(A{}).Field(0), "0"}, // Sees inside the field.
1110
1111 // verbs apply to the extracted value too.
1112 {"%s", reflect.ValueOf("hello"), "hello"},
1113 {"%q", reflect.ValueOf("hello"), `"hello"`},
1114 {"%#04x", reflect.ValueOf(256), "0x0100"},
1115
1116 // invalid reflect.Value doesn't crash.
1117 {"%v", reflect.Value{}, "<invalid reflect.Value>"},
1118 {"%v", &reflect.Value{}, "<invalid Value>"},
1119 {"%v", SI{reflect.Value{}}, "{<invalid Value>}"},
1120
1121 // Tests to check that not supported verbs generate an error string.
1122 {"%☠", nil, "%!☠(<nil>)"},
1123 {"%☠", any(nil), "%!☠(<nil>)"},
1124 {"%☠", int(0), "%!☠(int=0)"},
1125 {"%☠", uint(0), "%!☠(uint=0)"},
1126 {"%☠", []byte{0, 1}, "[%!☠(uint8=0) %!☠(uint8=1)]"},
1127 {"%☠", []uint8{0, 1}, "[%!☠(uint8=0) %!☠(uint8=1)]"},
1128 {"%☠", [1]byte{0}, "[%!☠(uint8=0)]"},
1129 {"%☠", [1]uint8{0}, "[%!☠(uint8=0)]"},
1130 {"%☠", "hello", "%!☠(string=hello)"},
1131 {"%☠", 1.2345678, "%!☠(float64=1.2345678)"},
1132 {"%☠", float32(1.2345678), "%!☠(float32=1.2345678)"},
1133 {"%☠", 1.2345678 + 1.2345678i, "%!☠(complex128=(1.2345678+1.2345678i))"},
1134 {"%☠", complex64(1.2345678 + 1.2345678i), "%!☠(complex64=(1.2345678+1.2345678i))"},
1135 {"%☠", &intVar, "%!☠(*int=0xPTR)"},
1136 {"%☠", make(chan int), "%!☠(chan int=0xPTR)"},
1137 {"%☠", func() {}, "%!☠(func()=0xPTR)"},
1138 {"%☠", reflect.ValueOf(renamedInt(0)), "%!☠(fmt_test.renamedInt=0)"},
1139 {"%☠", SI{renamedInt(0)}, "{%!☠(fmt_test.renamedInt=0)}"},
1140 {"%☠", &[]any{I(1), G(2)}, "&[%!☠(fmt_test.I=1) %!☠(fmt_test.G=2)]"},
1141 {"%☠", SI{&[]any{I(1), G(2)}}, "{%!☠(*[]interface {}=&[1 2])}"},
1142 {"%☠", reflect.Value{}, "<invalid reflect.Value>"},
1143 {"%☠", map[float64]int{NaN: 1}, "map[%!☠(float64=NaN):%!☠(int=1)]"},
1144 }
1145
1146 // zeroFill generates zero-filled strings of the specified width. The length
1147 // of the suffix (but not the prefix) is compensated for in the width calculation.
1148 func zeroFill(prefix string, width int, suffix string) string {
1149 return prefix + strings.Repeat("0", width-len(suffix)) + suffix
1150 }
1151
1152 func TestSprintf(t *testing.T) {
1153 for _, tt := range fmtTests {
1154 s := Sprintf(tt.fmt, tt.val)
1155 i := strings.Index(tt.out, "PTR")
1156 if i >= 0 && i < len(s) {
1157 var pattern, chars string
1158 switch {
1159 case strings.HasPrefix(tt.out[i:], "PTR_b"):
1160 pattern = "PTR_b"
1161 chars = "01"
1162 case strings.HasPrefix(tt.out[i:], "PTR_o"):
1163 pattern = "PTR_o"
1164 chars = "01234567"
1165 case strings.HasPrefix(tt.out[i:], "PTR_d"):
1166 pattern = "PTR_d"
1167 chars = "0123456789"
1168 case strings.HasPrefix(tt.out[i:], "PTR_x"):
1169 pattern = "PTR_x"
1170 chars = "0123456789abcdef"
1171 case strings.HasPrefix(tt.out[i:], "PTR_X"):
1172 pattern = "PTR_X"
1173 chars = "0123456789ABCDEF"
1174 default:
1175 pattern = "PTR"
1176 chars = "0123456789abcdefABCDEF"
1177 }
1178 p := s[:i] + pattern
1179 for j := i; j < len(s); j++ {
1180 if !strings.ContainsRune(chars, rune(s[j])) {
1181 p += s[j:]
1182 break
1183 }
1184 }
1185 s = p
1186 }
1187 if s != tt.out {
1188 if _, ok := tt.val.(string); ok {
1189 // Don't requote the already-quoted strings.
1190 // It's too confusing to read the errors.
1191 t.Errorf("Sprintf(%q, %q) = <%s> want <%s>", tt.fmt, tt.val, s, tt.out)
1192 } else {
1193 t.Errorf("Sprintf(%q, %v) = %q want %q", tt.fmt, tt.val, s, tt.out)
1194 }
1195 }
1196 }
1197 }
1198
1199 // TestComplexFormatting checks that a complex always formats to the same
1200 // thing as if done by hand with two singleton prints.
1201 func TestComplexFormatting(t *testing.T) {
1202 var yesNo = []bool{true, false}
1203 var values = []float64{1, 0, -1, posInf, negInf, NaN}
1204 for _, plus := range yesNo {
1205 for _, zero := range yesNo {
1206 for _, space := range yesNo {
1207 for _, char := range "fFeEgG" {
1208 realFmt := "%"
1209 if zero {
1210 realFmt += "0"
1211 }
1212 if space {
1213 realFmt += " "
1214 }
1215 if plus {
1216 realFmt += "+"
1217 }
1218 realFmt += "10.2"
1219 realFmt += string(char)
1220 // Imaginary part always has a sign, so force + and ignore space.
1221 imagFmt := "%"
1222 if zero {
1223 imagFmt += "0"
1224 }
1225 imagFmt += "+"
1226 imagFmt += "10.2"
1227 imagFmt += string(char)
1228 for _, realValue := range values {
1229 for _, imagValue := range values {
1230 one := Sprintf(realFmt, complex(realValue, imagValue))
1231 two := Sprintf("("+realFmt+imagFmt+"i)", realValue, imagValue)
1232 if one != two {
1233 t.Error(f, one, two)
1234 }
1235 }
1236 }
1237 }
1238 }
1239 }
1240 }
1241 }
1242
1243 type SE []any // slice of empty; notational compactness.
1244
1245 var reorderTests = []struct {
1246 fmt string
1247 val SE
1248 out string
1249 }{
1250 {"%[1]d", SE{1}, "1"},
1251 {"%[2]d", SE{2, 1}, "1"},
1252 {"%[2]d %[1]d", SE{1, 2}, "2 1"},
1253 {"%[2]*[1]d", SE{2, 5}, " 2"},
1254 {"%6.2f", SE{12.0}, " 12.00"}, // Explicit version of next line.
1255 {"%[3]*.[2]*[1]f", SE{12.0, 2, 6}, " 12.00"},
1256 {"%[1]*.[2]*[3]f", SE{6, 2, 12.0}, " 12.00"},
1257 {"%10f", SE{12.0}, " 12.000000"},
1258 {"%[1]*[3]f", SE{10, 99, 12.0}, " 12.000000"},
1259 {"%.6f", SE{12.0}, "12.000000"}, // Explicit version of next line.
1260 {"%.[1]*[3]f", SE{6, 99, 12.0}, "12.000000"},
1261 {"%6.f", SE{12.0}, " 12"}, // // Explicit version of next line; empty precision means zero.
1262 {"%[1]*.[3]f", SE{6, 3, 12.0}, " 12"},
1263 // An actual use! Print the same arguments twice.
1264 {"%d %d %d %#[1]o %#o %#o", SE{11, 12, 13}, "11 12 13 013 014 015"},
1265
1266 // Erroneous cases.
1267 {"%[d", SE{2, 1}, "%!d(BADINDEX)"},
1268 {"%]d", SE{2, 1}, "%!](int=2)d%!(EXTRA int=1)"},
1269 {"%[]d", SE{2, 1}, "%!d(BADINDEX)"},
1270 {"%[-3]d", SE{2, 1}, "%!d(BADINDEX)"},
1271 {"%[99]d", SE{2, 1}, "%!d(BADINDEX)"},
1272 {"%[3]", SE{2, 1}, "%!(NOVERB)"},
1273 {"%[1].2d", SE{5, 6}, "%!d(BADINDEX)"},
1274 {"%[1]2d", SE{2, 1}, "%!d(BADINDEX)"},
1275 {"%3.[2]d", SE{7}, "%!d(BADINDEX)"},
1276 {"%.[2]d", SE{7}, "%!d(BADINDEX)"},
1277 {"%d %d %d %#[1]o %#o %#o %#o", SE{11, 12, 13}, "11 12 13 013 014 015 %!o(MISSING)"},
1278 {"%[5]d %[2]d %d", SE{1, 2, 3}, "%!d(BADINDEX) 2 3"},
1279 {"%d %[3]d %d", SE{1, 2}, "1 %!d(BADINDEX) 2"}, // Erroneous index does not affect sequence.
1280 {"%.[]", SE{}, "%!](BADINDEX)"}, // Issue 10675
1281 {"%.-3d", SE{42}, "%!-(int=42)3d"}, // TODO: Should this set return better error messages?
1282 {"%2147483648d", SE{42}, "%!(NOVERB)%!(EXTRA int=42)"},
1283 {"%-2147483648d", SE{42}, "%!(NOVERB)%!(EXTRA int=42)"},
1284 {"%.2147483648d", SE{42}, "%!(NOVERB)%!(EXTRA int=42)"},
1285 }
1286
1287 func TestReorder(t *testing.T) {
1288 for _, tt := range reorderTests {
1289 s := Sprintf(tt.fmt, tt.val...)
1290 if s != tt.out {
1291 t.Errorf("Sprintf(%q, %v) = <%s> want <%s>", tt.fmt, tt.val, s, tt.out)
1292 }
1293 }
1294 }
1295
1296 func BenchmarkSprintfPadding(b *testing.B) {
1297 b.RunParallel(func(pb *testing.PB) {
1298 for pb.Next() {
1299 _ = Sprintf("%16f", 1.0)
1300 }
1301 })
1302 }
1303
1304 func BenchmarkSprintfEmpty(b *testing.B) {
1305 b.RunParallel(func(pb *testing.PB) {
1306 for pb.Next() {
1307 _ = Sprintf("")
1308 }
1309 })
1310 }
1311
1312 func BenchmarkSprintfString(b *testing.B) {
1313 b.RunParallel(func(pb *testing.PB) {
1314 for pb.Next() {
1315 _ = Sprintf("%s", "hello")
1316 }
1317 })
1318 }
1319
1320 func BenchmarkSprintfTruncateString(b *testing.B) {
1321 b.RunParallel(func(pb *testing.PB) {
1322 for pb.Next() {
1323 _ = Sprintf("%.3s", "日本語日本語日本語日本語")
1324 }
1325 })
1326 }
1327
1328 func BenchmarkSprintfTruncateBytes(b *testing.B) {
1329 var bytes any = []byte("日本語日本語日本語日本語")
1330 b.RunParallel(func(pb *testing.PB) {
1331 for pb.Next() {
1332 _ = Sprintf("%.3s", bytes)
1333 }
1334 })
1335 }
1336
1337 func BenchmarkSprintfSlowParsingPath(b *testing.B) {
1338 b.RunParallel(func(pb *testing.PB) {
1339 for pb.Next() {
1340 _ = Sprintf("%.v", nil)
1341 }
1342 })
1343 }
1344
1345 func BenchmarkSprintfQuoteString(b *testing.B) {
1346 b.RunParallel(func(pb *testing.PB) {
1347 for pb.Next() {
1348 _ = Sprintf("%q", "日本語日本語日本語")
1349 }
1350 })
1351 }
1352
1353 func BenchmarkSprintfInt(b *testing.B) {
1354 b.RunParallel(func(pb *testing.PB) {
1355 for pb.Next() {
1356 _ = Sprintf("%d", 5)
1357 }
1358 })
1359 }
1360
1361 func BenchmarkSprintfIntInt(b *testing.B) {
1362 b.RunParallel(func(pb *testing.PB) {
1363 for pb.Next() {
1364 _ = Sprintf("%d %d", 5, 6)
1365 }
1366 })
1367 }
1368
1369 func BenchmarkSprintfPrefixedInt(b *testing.B) {
1370 b.RunParallel(func(pb *testing.PB) {
1371 for pb.Next() {
1372 _ = Sprintf("This is some meaningless prefix text that needs to be scanned %d", 6)
1373 }
1374 })
1375 }
1376
1377 func BenchmarkSprintfFloat(b *testing.B) {
1378 b.RunParallel(func(pb *testing.PB) {
1379 for pb.Next() {
1380 _ = Sprintf("%g", 5.23184)
1381 }
1382 })
1383 }
1384
1385 func BenchmarkSprintfComplex(b *testing.B) {
1386 b.RunParallel(func(pb *testing.PB) {
1387 for pb.Next() {
1388 _ = Sprintf("%f", 5.23184+5.23184i)
1389 }
1390 })
1391 }
1392
1393 func BenchmarkSprintfBoolean(b *testing.B) {
1394 b.RunParallel(func(pb *testing.PB) {
1395 for pb.Next() {
1396 _ = Sprintf("%t", true)
1397 }
1398 })
1399 }
1400
1401 func BenchmarkSprintfHexString(b *testing.B) {
1402 b.RunParallel(func(pb *testing.PB) {
1403 for pb.Next() {
1404 _ = Sprintf("% #x", "0123456789abcdef")
1405 }
1406 })
1407 }
1408
1409 func BenchmarkSprintfHexBytes(b *testing.B) {
1410 data := []byte("0123456789abcdef")
1411 b.RunParallel(func(pb *testing.PB) {
1412 for pb.Next() {
1413 _ = Sprintf("% #x", data)
1414 }
1415 })
1416 }
1417
1418 func BenchmarkSprintfBytes(b *testing.B) {
1419 data := []byte("0123456789abcdef")
1420 b.RunParallel(func(pb *testing.PB) {
1421 for pb.Next() {
1422 _ = Sprintf("%v", data)
1423 }
1424 })
1425 }
1426
1427 func BenchmarkSprintfStringer(b *testing.B) {
1428 stringer := I(12345)
1429 b.RunParallel(func(pb *testing.PB) {
1430 for pb.Next() {
1431 _ = Sprintf("%v", stringer)
1432 }
1433 })
1434 }
1435
1436 func BenchmarkSprintfStructure(b *testing.B) {
1437 s := &[]any{SI{12345}, map[int]string{0: "hello"}}
1438 b.RunParallel(func(pb *testing.PB) {
1439 for pb.Next() {
1440 _ = Sprintf("%#v", s)
1441 }
1442 })
1443 }
1444
1445 func BenchmarkManyArgs(b *testing.B) {
1446 b.RunParallel(func(pb *testing.PB) {
1447 var buf bytes.Buffer
1448 for pb.Next() {
1449 buf.Reset()
1450 Fprintf(&buf, "%2d/%2d/%2d %d:%d:%d %s %s\n", 3, 4, 5, 11, 12, 13, "hello", "world")
1451 }
1452 })
1453 }
1454
1455 func BenchmarkFprintInt(b *testing.B) {
1456 var buf bytes.Buffer
1457 for i := 0; i < b.N; i++ {
1458 buf.Reset()
1459 Fprint(&buf, 123456)
1460 }
1461 }
1462
1463 func BenchmarkFprintfBytes(b *testing.B) {
1464 data := []byte(string("0123456789"))
1465 var buf bytes.Buffer
1466 for i := 0; i < b.N; i++ {
1467 buf.Reset()
1468 Fprintf(&buf, "%s", data)
1469 }
1470 }
1471
1472 func BenchmarkFprintIntNoAlloc(b *testing.B) {
1473 var x any = 123456
1474 var buf bytes.Buffer
1475 for i := 0; i < b.N; i++ {
1476 buf.Reset()
1477 Fprint(&buf, x)
1478 }
1479 }
1480
1481 var mallocBuf bytes.Buffer
1482 var mallocPointer *int // A pointer so we know the interface value won't allocate.
1483
1484 var mallocTest = []struct {
1485 count int
1486 desc string
1487 fn func()
1488 }{
1489 {0, `Sprintf("")`, func() { _ = Sprintf("") }},
1490 {1, `Sprintf("xxx")`, func() { _ = Sprintf("xxx") }},
1491 {0, `Sprintf("%x")`, func() { _ = Sprintf("%x", 7) }},
1492 {1, `Sprintf("%x")`, func() { _ = Sprintf("%x", 1<<16) }},
1493 {3, `Sprintf("%80000s")`, func() { _ = Sprintf("%80000s", "hello") }}, // large buffer (>64KB)
1494 {1, `Sprintf("%s")`, func() { _ = Sprintf("%s", "hello") }},
1495 {1, `Sprintf("%x %x")`, func() { _ = Sprintf("%x %x", 7, 112) }},
1496 {1, `Sprintf("%g")`, func() { _ = Sprintf("%g", float32(3.14159)) }},
1497 {0, `Fprintf(buf, "%s")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%s", "hello") }},
1498 {0, `Fprintf(buf, "%s")`, func() { mallocBuf.Reset(); s := "hello"; Fprintf(&mallocBuf, "%s", s) }},
1499 {1, `Fprintf(buf, "%s")`, func() { mallocBuf.Reset(); s := "hello"; Fprintf(&mallocBuf, "%s", noliteral(s)) }},
1500 {0, `Fprintf(buf, "%x")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%x", 7) }},
1501 {0, `Fprintf(buf, "%x")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%x", 1<<16) }},
1502 {0, `Fprintf(buf, "%x")`, func() { mallocBuf.Reset(); i := 1 << 16; Fprintf(&mallocBuf, "%x", i) }},
1503 {1, `Fprintf(buf, "%x")`, func() { mallocBuf.Reset(); i := 1 << 16; Fprintf(&mallocBuf, "%x", noliteral(i)) }},
1504 {4, `Fprintf(buf, "%v")`, func() { mallocBuf.Reset(); s := []int{1, 2}; Fprintf(&mallocBuf, "%v", s) }},
1505 {0, `Fprintf(buf, "%v")`, func() { mallocBuf.Reset(); type P struct{ x, y int }; Fprintf(&mallocBuf, "%v", P{1, 2}) }},
1506 {1, `Fprintf(buf, "%v")`, func() { mallocBuf.Reset(); type P struct{ x, y int }; Fprintf(&mallocBuf, "%v", noliteral(P{1, 2})) }},
1507 {2, `Fprintf(buf, "%80000s")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%80000s", "hello") }}, // large buffer (>64KB)
1508 // If the interface value doesn't need to allocate, amortized allocation overhead should be zero.
1509 {0, `Fprintf(buf, "%x %x %x")`, func() {
1510 mallocBuf.Reset()
1511 Fprintf(&mallocBuf, "%x %x %x", mallocPointer, mallocPointer, mallocPointer)
1512 }},
1513 }
1514
1515 var _ bytes.Buffer
1516
1517 func TestCountMallocs(t *testing.T) {
1518 switch {
1519 case testing.Short():
1520 t.Skip("skipping malloc count in short mode")
1521 case race.Enabled:
1522 t.Skip("skipping malloc count under race detector")
1523 }
1524 for _, mt := range mallocTest {
1525 mallocs := testing.AllocsPerRun(100, mt.fn)
1526 if got, max := mallocs, float64(mt.count); got != max {
1527 t.Errorf("%s: got %v allocs, want %v", mt.desc, got, max)
1528 }
1529 }
1530 }
1531
1532 type flagPrinter struct{}
1533
1534 func (flagPrinter) Format(f State, c rune) {
1535 s := "%"
1536 for i := 0; i < 128; i++ {
1537 if f.Flag(i) {
1538 s += string(rune(i))
1539 }
1540 }
1541 if w, ok := f.Width(); ok {
1542 s += Sprintf("%d", w)
1543 }
1544 if p, ok := f.Precision(); ok {
1545 s += Sprintf(".%d", p)
1546 }
1547 s += string(c)
1548 io.WriteString(f, "["+s+"]")
1549 }
1550
1551 var flagtests = []struct {
1552 in string
1553 out string
1554 }{
1555 {"%a", "[%a]"},
1556 {"%-a", "[%-a]"},
1557 {"%+a", "[%+a]"},
1558 {"%#a", "[%#a]"},
1559 {"% a", "[% a]"},
1560 {"%0a", "[%0a]"},
1561 {"%1.2a", "[%1.2a]"},
1562 {"%-1.2a", "[%-1.2a]"},
1563 {"%+1.2a", "[%+1.2a]"},
1564 {"%-+1.2a", "[%+-1.2a]"},
1565 {"%-+1.2abc", "[%+-1.2a]bc"},
1566 {"%-1.2abc", "[%-1.2a]bc"},
1567 {"%-0abc", "[%-0a]bc"},
1568 }
1569
1570 func TestFlagParser(t *testing.T) {
1571 var flagprinter flagPrinter
1572 for _, tt := range flagtests {
1573 s := Sprintf(tt.in, &flagprinter)
1574 if s != tt.out {
1575 t.Errorf("Sprintf(%q, &flagprinter) => %q, want %q", tt.in, s, tt.out)
1576 }
1577 }
1578 }
1579
1580 func TestStructPrinter(t *testing.T) {
1581 type T struct {
1582 a string
1583 b string
1584 c int
1585 }
1586 var s T
1587 s.a = "abc"
1588 s.b = "def"
1589 s.c = 123
1590 var tests = []struct {
1591 fmt string
1592 out string
1593 }{
1594 {"%v", "{abc def 123}"},
1595 {"%+v", "{a:abc b:def c:123}"},
1596 {"%#v", `fmt_test.T{a:"abc", b:"def", c:123}`},
1597 }
1598 for _, tt := range tests {
1599 out := Sprintf(tt.fmt, s)
1600 if out != tt.out {
1601 t.Errorf("Sprintf(%q, s) = %#q, want %#q", tt.fmt, out, tt.out)
1602 }
1603 // The same but with a pointer.
1604 out = Sprintf(tt.fmt, &s)
1605 if out != "&"+tt.out {
1606 t.Errorf("Sprintf(%q, &s) = %#q, want %#q", tt.fmt, out, "&"+tt.out)
1607 }
1608 }
1609 }
1610
1611 func TestSlicePrinter(t *testing.T) {
1612 slice := []int{}
1613 s := Sprint(slice)
1614 if s != "[]" {
1615 t.Errorf("empty slice printed as %q not %q", s, "[]")
1616 }
1617 slice = []int{1, 2, 3}
1618 s = Sprint(slice)
1619 if s != "[1 2 3]" {
1620 t.Errorf("slice: got %q expected %q", s, "[1 2 3]")
1621 }
1622 s = Sprint(&slice)
1623 if s != "&[1 2 3]" {
1624 t.Errorf("&slice: got %q expected %q", s, "&[1 2 3]")
1625 }
1626 }
1627
1628 // presentInMap checks map printing using substrings so we don't depend on the
1629 // print order.
1630 func presentInMap(s string, a []string, t *testing.T) {
1631 for i := 0; i < len(a); i++ {
1632 loc := strings.Index(s, a[i])
1633 if loc < 0 {
1634 t.Errorf("map print: expected to find %q in %q", a[i], s)
1635 }
1636 // make sure the match ends here
1637 loc += len(a[i])
1638 if loc >= len(s) || (s[loc] != ' ' && s[loc] != ']') {
1639 t.Errorf("map print: %q not properly terminated in %q", a[i], s)
1640 }
1641 }
1642 }
1643
1644 func TestMapPrinter(t *testing.T) {
1645 m0 := make(map[int]string)
1646 s := Sprint(m0)
1647 if s != "map[]" {
1648 t.Errorf("empty map printed as %q not %q", s, "map[]")
1649 }
1650 m1 := map[int]string{1: "one", 2: "two", 3: "three"}
1651 a := []string{"1:one", "2:two", "3:three"}
1652 presentInMap(Sprintf("%v", m1), a, t)
1653 presentInMap(Sprint(m1), a, t)
1654 // Pointer to map prints the same but with initial &.
1655 if !strings.HasPrefix(Sprint(&m1), "&") {
1656 t.Errorf("no initial & for address of map")
1657 }
1658 presentInMap(Sprintf("%v", &m1), a, t)
1659 presentInMap(Sprint(&m1), a, t)
1660 }
1661
1662 func TestEmptyMap(t *testing.T) {
1663 const emptyMapStr = "map[]"
1664 var m map[string]int
1665 s := Sprint(m)
1666 if s != emptyMapStr {
1667 t.Errorf("nil map printed as %q not %q", s, emptyMapStr)
1668 }
1669 m = make(map[string]int)
1670 s = Sprint(m)
1671 if s != emptyMapStr {
1672 t.Errorf("empty map printed as %q not %q", s, emptyMapStr)
1673 }
1674 }
1675
1676 // TestBlank checks that Sprint (and hence Print, Fprint) puts spaces in the
1677 // right places, that is, between arg pairs in which neither is a string.
1678 func TestBlank(t *testing.T) {
1679 got := Sprint("<", 1, ">:", 1, 2, 3, "!")
1680 expect := "<1>:1 2 3!"
1681 if got != expect {
1682 t.Errorf("got %q expected %q", got, expect)
1683 }
1684 }
1685
1686 // TestBlankln checks that Sprintln (and hence Println, Fprintln) puts spaces in
1687 // the right places, that is, between all arg pairs.
1688 func TestBlankln(t *testing.T) {
1689 got := Sprintln("<", 1, ">:", 1, 2, 3, "!")
1690 expect := "< 1 >: 1 2 3 !\n"
1691 if got != expect {
1692 t.Errorf("got %q expected %q", got, expect)
1693 }
1694 }
1695
1696 // TestFormatterPrintln checks Formatter with Sprint, Sprintln, Sprintf.
1697 func TestFormatterPrintln(t *testing.T) {
1698 f := F(1)
1699 expect := "<v=F(1)>\n"
1700 s := Sprint(f, "\n")
1701 if s != expect {
1702 t.Errorf("Sprint wrong with Formatter: expected %q got %q", expect, s)
1703 }
1704 s = Sprintln(f)
1705 if s != expect {
1706 t.Errorf("Sprintln wrong with Formatter: expected %q got %q", expect, s)
1707 }
1708 s = Sprintf("%v\n", f)
1709 if s != expect {
1710 t.Errorf("Sprintf wrong with Formatter: expected %q got %q", expect, s)
1711 }
1712 }
1713
1714 func args(a ...any) []any { return a }
1715
1716 var startests = []struct {
1717 fmt string
1718 in []any
1719 out string
1720 }{
1721 {"%*d", args(4, 42), " 42"},
1722 {"%-*d", args(4, 42), "42 "},
1723 {"%*d", args(-4, 42), "42 "},
1724 {"%-*d", args(-4, 42), "42 "},
1725 {"%.*d", args(4, 42), "0042"},
1726 {"%*.*d", args(8, 4, 42), " 0042"},
1727 {"%0*d", args(4, 42), "0042"},
1728 // Some non-int types for width. (Issue 10732).
1729 {"%0*d", args(uint(4), 42), "0042"},
1730 {"%0*d", args(uint64(4), 42), "0042"},
1731 {"%0*d", args('\x04', 42), "0042"},
1732 {"%0*d", args(uintptr(4), 42), "0042"},
1733
1734 // erroneous
1735 {"%*d", args(nil, 42), "%!(BADWIDTH)42"},
1736 {"%*d", args(int(1e7), 42), "%!(BADWIDTH)42"},
1737 {"%*d", args(int(-1e7), 42), "%!(BADWIDTH)42"},
1738 {"%.*d", args(nil, 42), "%!(BADPREC)42"},
1739 {"%.*d", args(-1, 42), "%!(BADPREC)42"},
1740 {"%.*d", args(int(1e7), 42), "%!(BADPREC)42"},
1741 {"%.*d", args(uint(1e7), 42), "%!(BADPREC)42"},
1742 {"%.*d", args(uint64(1<<63), 42), "%!(BADPREC)42"}, // Huge negative (-inf).
1743 {"%.*d", args(uint64(1<<64-1), 42), "%!(BADPREC)42"}, // Small negative (-1).
1744 {"%*d", args(5, "foo"), "%!d(string= foo)"},
1745 {"%*% %d", args(20, 5), "% 5"},
1746 {"%*", args(4), "%!(NOVERB)"},
1747 }
1748
1749 func TestWidthAndPrecision(t *testing.T) {
1750 for i, tt := range startests {
1751 s := Sprintf(tt.fmt, tt.in...)
1752 if s != tt.out {
1753 t.Errorf("#%d: %q: got %q expected %q", i, tt.fmt, s, tt.out)
1754 }
1755 }
1756 }
1757
1758 // PanicS is a type that panics in String.
1759 type PanicS struct {
1760 message any
1761 }
1762
1763 // Value receiver.
1764 func (p PanicS) String() string {
1765 panic(p.message)
1766 }
1767
1768 // PanicGo is a type that panics in GoString.
1769 type PanicGo struct {
1770 message any
1771 }
1772
1773 // Value receiver.
1774 func (p PanicGo) GoString() string {
1775 panic(p.message)
1776 }
1777
1778 // PanicF is a type that panics in Format.
1779 type PanicF struct {
1780 message any
1781 }
1782
1783 // Value receiver.
1784 func (p PanicF) Format(f State, c rune) {
1785 panic(p.message)
1786 }
1787
1788 var panictests = []struct {
1789 fmt string
1790 in any
1791 out string
1792 }{
1793 // String
1794 {"%s", (*PanicS)(nil), "<nil>"}, // nil pointer special case
1795 {"%s", PanicS{io.ErrUnexpectedEOF}, "%!s(PANIC=String method: unexpected EOF)"},
1796 {"%s", PanicS{3}, "%!s(PANIC=String method: 3)"},
1797 // GoString
1798 {"%#v", (*PanicGo)(nil), "<nil>"}, // nil pointer special case
1799 {"%#v", PanicGo{io.ErrUnexpectedEOF}, "%!v(PANIC=GoString method: unexpected EOF)"},
1800 {"%#v", PanicGo{3}, "%!v(PANIC=GoString method: 3)"},
1801 // Issue 18282. catchPanic should not clear fmtFlags permanently.
1802 {"%#v", []any{PanicGo{3}, PanicGo{3}}, "[]interface {}{%!v(PANIC=GoString method: 3), %!v(PANIC=GoString method: 3)}"},
1803 // Format
1804 {"%s", (*PanicF)(nil), "<nil>"}, // nil pointer special case
1805 {"%s", PanicF{io.ErrUnexpectedEOF}, "%!s(PANIC=Format method: unexpected EOF)"},
1806 {"%s", PanicF{3}, "%!s(PANIC=Format method: 3)"},
1807 }
1808
1809 func TestPanics(t *testing.T) {
1810 for i, tt := range panictests {
1811 s := Sprintf(tt.fmt, tt.in)
1812 if s != tt.out {
1813 t.Errorf("%d: %q: got %q expected %q", i, tt.fmt, s, tt.out)
1814 }
1815 }
1816 }
1817
1818 // recurCount tests that erroneous String routine doesn't cause fatal recursion.
1819 var recurCount = 0
1820
1821 type Recur struct {
1822 i int
1823 failed *bool
1824 }
1825
1826 func (r *Recur) String() string {
1827 if recurCount++; recurCount > 10 {
1828 *r.failed = true
1829 return "FAIL"
1830 }
1831 // This will call badVerb. Before the fix, that would cause us to recur into
1832 // this routine to print %!p(value). Now we don't call the user's method
1833 // during an error.
1834 return Sprintf("recur@%p value: %d", r, r.i)
1835 }
1836
1837 func TestBadVerbRecursion(t *testing.T) {
1838 failed := false
1839 r := &Recur{3, &failed}
1840 _ = Sprintf("recur@%p value: %d\n", &r, r.i)
1841 if failed {
1842 t.Error("fail with pointer")
1843 }
1844 failed = false
1845 r = &Recur{4, &failed}
1846 _ = Sprintf("recur@%p, value: %d\n", r, r.i)
1847 if failed {
1848 t.Error("fail with value")
1849 }
1850 }
1851
1852 func TestIsSpace(t *testing.T) {
1853 // This tests the internal isSpace function.
1854 // IsSpace = isSpace is defined in export_test.go.
1855 for i := rune(0); i <= unicode.MaxRune; i++ {
1856 if IsSpace(i) != unicode.IsSpace(i) {
1857 t.Errorf("isSpace(%U) = %v, want %v", i, IsSpace(i), unicode.IsSpace(i))
1858 }
1859 }
1860 }
1861
1862 func hideFromVet(s string) string { return s }
1863
1864 func TestNilDoesNotBecomeTyped(t *testing.T) {
1865 type A struct{}
1866 type B struct{}
1867 var a *A = nil
1868 var b B = B{}
1869 got := Sprintf(hideFromVet("%s %s %s %s %s"), nil, a, nil, b, nil)
1870 const expect = "%!s(<nil>) %!s(*fmt_test.A=<nil>) %!s(<nil>) {} %!s(<nil>)"
1871 if got != expect {
1872 t.Errorf("expected:\n\t%q\ngot:\n\t%q", expect, got)
1873 }
1874 }
1875
1876 var formatterFlagTests = []struct {
1877 in string
1878 val any
1879 out string
1880 }{
1881 // scalar values with the (unused by fmt) 'a' verb.
1882 {"%a", flagPrinter{}, "[%a]"},
1883 {"%-a", flagPrinter{}, "[%-a]"},
1884 {"%+a", flagPrinter{}, "[%+a]"},
1885 {"%#a", flagPrinter{}, "[%#a]"},
1886 {"% a", flagPrinter{}, "[% a]"},
1887 {"%0a", flagPrinter{}, "[%0a]"},
1888 {"%1.2a", flagPrinter{}, "[%1.2a]"},
1889 {"%-1.2a", flagPrinter{}, "[%-1.2a]"},
1890 {"%+1.2a", flagPrinter{}, "[%+1.2a]"},
1891 {"%-+1.2a", flagPrinter{}, "[%+-1.2a]"},
1892 {"%-+1.2abc", flagPrinter{}, "[%+-1.2a]bc"},
1893 {"%-1.2abc", flagPrinter{}, "[%-1.2a]bc"},
1894 {"%-0abc", flagPrinter{}, "[%-0a]bc"},
1895
1896 // composite values with the 'a' verb
1897 {"%a", [1]flagPrinter{}, "[[%a]]"},
1898 {"%-a", [1]flagPrinter{}, "[[%-a]]"},
1899 {"%+a", [1]flagPrinter{}, "[[%+a]]"},
1900 {"%#a", [1]flagPrinter{}, "[[%#a]]"},
1901 {"% a", [1]flagPrinter{}, "[[% a]]"},
1902 {"%0a", [1]flagPrinter{}, "[[%0a]]"},
1903 {"%1.2a", [1]flagPrinter{}, "[[%1.2a]]"},
1904 {"%-1.2a", [1]flagPrinter{}, "[[%-1.2a]]"},
1905 {"%+1.2a", [1]flagPrinter{}, "[[%+1.2a]]"},
1906 {"%-+1.2a", [1]flagPrinter{}, "[[%+-1.2a]]"},
1907 {"%-+1.2abc", [1]flagPrinter{}, "[[%+-1.2a]]bc"},
1908 {"%-1.2abc", [1]flagPrinter{}, "[[%-1.2a]]bc"},
1909 {"%-0abc", [1]flagPrinter{}, "[[%-0a]]bc"},
1910
1911 // simple values with the 'v' verb
1912 {"%v", flagPrinter{}, "[%v]"},
1913 {"%-v", flagPrinter{}, "[%-v]"},
1914 {"%+v", flagPrinter{}, "[%+v]"},
1915 {"%#v", flagPrinter{}, "[%#v]"},
1916 {"% v", flagPrinter{}, "[% v]"},
1917 {"%0v", flagPrinter{}, "[%0v]"},
1918 {"%1.2v", flagPrinter{}, "[%1.2v]"},
1919 {"%-1.2v", flagPrinter{}, "[%-1.2v]"},
1920 {"%+1.2v", flagPrinter{}, "[%+1.2v]"},
1921 {"%-+1.2v", flagPrinter{}, "[%+-1.2v]"},
1922 {"%-+1.2vbc", flagPrinter{}, "[%+-1.2v]bc"},
1923 {"%-1.2vbc", flagPrinter{}, "[%-1.2v]bc"},
1924 {"%-0vbc", flagPrinter{}, "[%-0v]bc"},
1925
1926 // composite values with the 'v' verb.
1927 {"%v", [1]flagPrinter{}, "[[%v]]"},
1928 {"%-v", [1]flagPrinter{}, "[[%-v]]"},
1929 {"%+v", [1]flagPrinter{}, "[[%+v]]"},
1930 {"%#v", [1]flagPrinter{}, "[1]fmt_test.flagPrinter{[%#v]}"},
1931 {"% v", [1]flagPrinter{}, "[[% v]]"},
1932 {"%0v", [1]flagPrinter{}, "[[%0v]]"},
1933 {"%1.2v", [1]flagPrinter{}, "[[%1.2v]]"},
1934 {"%-1.2v", [1]flagPrinter{}, "[[%-1.2v]]"},
1935 {"%+1.2v", [1]flagPrinter{}, "[[%+1.2v]]"},
1936 {"%-+1.2v", [1]flagPrinter{}, "[[%+-1.2v]]"},
1937 {"%-+1.2vbc", [1]flagPrinter{}, "[[%+-1.2v]]bc"},
1938 {"%-1.2vbc", [1]flagPrinter{}, "[[%-1.2v]]bc"},
1939 {"%-0vbc", [1]flagPrinter{}, "[[%-0v]]bc"},
1940 }
1941
1942 func TestFormatterFlags(t *testing.T) {
1943 for _, tt := range formatterFlagTests {
1944 s := Sprintf(tt.in, tt.val)
1945 if s != tt.out {
1946 t.Errorf("Sprintf(%q, %T) = %q, want %q", tt.in, tt.val, s, tt.out)
1947 }
1948 }
1949 }
1950
1951 func TestParsenum(t *testing.T) {
1952 testCases := []struct {
1953 s string
1954 start, end int
1955 num int
1956 isnum bool
1957 newi int
1958 }{
1959 {"a123", 0, 4, 0, false, 0},
1960 {"1234", 1, 1, 0, false, 1},
1961 {"123a", 0, 4, 123, true, 3},
1962 {"12a3", 0, 4, 12, true, 2},
1963 {"1234", 0, 4, 1234, true, 4},
1964 {"1a234", 1, 3, 0, false, 1},
1965 }
1966 for _, tt := range testCases {
1967 num, isnum, newi := Parsenum(tt.s, tt.start, tt.end)
1968 if num != tt.num || isnum != tt.isnum || newi != tt.newi {
1969 t.Errorf("parsenum(%q, %d, %d) = %d, %v, %d, want %d, %v, %d", tt.s, tt.start, tt.end, num, isnum, newi, tt.num, tt.isnum, tt.newi)
1970 }
1971 }
1972 }
1973
1974 // Test the various Append printers. The details are well tested above;
1975 // here we just make sure the byte slice is updated.
1976
1977 const (
1978 appendResult = "hello world, 23"
1979 hello = "hello "
1980 )
1981
1982 func TestAppendf(t *testing.T) {
1983 b := make([]byte, 100)
1984 b = b[:copy(b, hello)]
1985 got := Appendf(b, "world, %d", 23)
1986 if string(got) != appendResult {
1987 t.Fatalf("Appendf returns %q not %q", got, appendResult)
1988 }
1989 if &b[0] != &got[0] {
1990 t.Fatalf("Appendf allocated a new slice")
1991 }
1992 }
1993
1994 func TestAppend(t *testing.T) {
1995 b := make([]byte, 100)
1996 b = b[:copy(b, hello)]
1997 got := Append(b, "world", ", ", 23)
1998 if string(got) != appendResult {
1999 t.Fatalf("Append returns %q not %q", got, appendResult)
2000 }
2001 if &b[0] != &got[0] {
2002 t.Fatalf("Append allocated a new slice")
2003 }
2004 }
2005
2006 func TestAppendln(t *testing.T) {
2007 b := make([]byte, 100)
2008 b = b[:copy(b, hello)]
2009 got := Appendln(b, "world,", 23)
2010 if string(got) != appendResult+"\n" {
2011 t.Fatalf("Appendln returns %q not %q", got, appendResult+"\n")
2012 }
2013 if &b[0] != &got[0] {
2014 t.Fatalf("Appendln allocated a new slice")
2015 }
2016 }
2017
2018 // noliteral prevents escape analysis from recognizing a literal value.
2019 //
2020 //go:noinline
2021 func noliteral[T any](t T) T {
2022 return t
2023 }
2024
View as plain text