You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

1872 lines
58 KiB

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