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