package fmt_test
import (
+ "bytes"
. "fmt"
"io"
"math"
}
}
-
const b32 uint32 = 1<<32 - 1
const b64 uint64 = 1<<64 - 1
func (i I) String() string { return Sprintf("<%d>", int(i)) }
type B struct {
- i I
+ I I
j int
}
}
type S struct {
- f F // a struct field that Formats
- g G // a struct field that GoStrings
+ F F // a struct field that Formats
+ G G // a struct field that GoStrings
}
// A type with a String method with pointer receiver for testing %p
{"%q", `"`, `"\""`},
{"%q", "\a\b\f\r\n\t\v", `"\a\b\f\r\n\t\v"`},
{"%q", "abc\xffdef", `"abc\xffdef"`},
- {"%q", "\u263a", `"\u263a"`},
+ {"%q", "\u263a", `"☺"`},
+ {"%+q", "\u263a", `"\u263a"`},
{"%q", "\U0010ffff", `"\U0010ffff"`},
+ // escaped characters
+ {"%q", 'x', `'x'`},
+ {"%q", 0, `'\x00'`},
+ {"%q", '\n', `'\n'`},
+ {"%q", '\u0e00', `'\u0e00'`}, // not a printable rune.
+ {"%q", '\U000c2345', `'\U000c2345'`}, // not a printable rune.
+ {"%q", int64(0x7FFFFFFF), `%!q(int64=2147483647)`},
+ {"%q", uint64(0xFFFFFFFF), `%!q(uint64=4294967295)`},
+ {"%q", '"', `'"'`},
+ {"%q", '\'', `'\''`},
+ {"%q", "\u263a", `"☺"`},
+ {"%+q", "\u263a", `"\u263a"`},
+
// width
{"%5s", "abc", " abc"},
- {"%2s", "\u263a", " \u263a"},
+ {"%2s", "\u263a", " ☺"},
{"%-5s", "abc", "abc "},
+ {"%-8q", "abc", `"abc" `},
{"%05s", "abc", "00abc"},
+ {"%08q", "abc", `000"abc"`},
+ {"%5s", "abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"},
+ {"%.5s", "abcdefghijklmnopqrstuvwxyz", "abcde"},
+ {"%.5s", "日本語日本語", "日本語日本"},
+ {"%.5s", []byte("日本語日本語"), "日本語日本"},
+ {"%.5q", "abcdefghijklmnopqrstuvwxyz", `"abcde"`},
+ {"%.3q", "日本語日本語", `"日本語"`},
+ {"%.3q", []byte("日本語日本語"), `"日本語"`},
+ {"%10.1q", "日本語日本語", ` "日"`},
// integers
{"%d", 12345, "12345"},
{"%+d", 0, "+0"},
{"% d", 0, " 0"},
{"% d", 12345, " 12345"},
+ {"%.0d", 0, ""},
+ {"%.d", 0, ""},
// unicode format
{"%U", 0x1, "U+0001"},
+ {"%U", uint(0x1), "U+0001"},
{"%.8U", 0x2, "U+00000002"},
{"%U", 0x1234, "U+1234"},
{"%U", 0x12345, "U+12345"},
{"%10.6U", 0xABC, " U+000ABC"},
{"%-10.6U", 0xABC, "U+000ABC "},
+ {"%U", '\n', `U+000A`},
+ {"%#U", '\n', `U+000A`},
+ {"%U", 'x', `U+0078`},
+ {"%#U", 'x', `U+0078 'x'`},
+ {"%U", '\u263a', `U+263A`},
+ {"%#U", '\u263a', `U+263A '☺'`},
// floats
{"%+.3e", 0.0, "+0.000e+00"},
{"%+v", A{1, 2, "a", []int{1, 2}}, `{i:1 j:2 s:a x:[1 2]}`},
// +v on structs with Stringable items
- {"%+v", B{1, 2}, `{i:<1> j:2}`},
- {"%+v", C{1, B{2, 3}}, `{i:1 B:{i:<2> j:3}}`},
+ {"%+v", B{1, 2}, `{I:<1> j:2}`},
+ {"%+v", C{1, B{2, 3}}, `{i:1 B:{I:<2> j:3}}`},
// q on Stringable items
{"%s", I(23), `<23>`},
{"%#v", make(chan int), "(chan int)(0xPTR)"},
{"%#v", uint64(1<<64 - 1), "0xffffffffffffffff"},
{"%#v", 1000000000, "1000000000"},
- {"%#v", map[string]int{"a": 1, "b": 2}, `map[string] int{"a":1, "b":2}`},
- {"%#v", map[string]B{"a": {1, 2}, "b": {3, 4}}, `map[string] fmt_test.B{"a":fmt_test.B{i:1, j:2}, "b":fmt_test.B{i:3, j:4}}`},
+ {"%#v", map[string]int{"a": 1}, `map[string] int{"a":1}`},
+ {"%#v", map[string]B{"a": {1, 2}}, `map[string] fmt_test.B{"a":fmt_test.B{I:1, j:2}}`},
{"%#v", []string{"a", "b"}, `[]string{"a", "b"}`},
// slices with other formats
// Formatter
{"%x", F(1), "<x=F(1)>"},
{"%x", G(2), "2"},
- {"%+v", S{F(4), G(5)}, "{f:<v=F(4)> g:5}"},
+ {"%+v", S{F(4), G(5)}, "{F:<v=F(4)> G:5}"},
// GoStringer
{"%#v", G(6), "GoString(6)"},
- {"%#v", S{F(7), G(8)}, "fmt_test.S{f:<v=F(7)>, g:GoString(8)}"},
+ {"%#v", S{F(7), G(8)}, "fmt_test.S{F:<v=F(7)>, G:GoString(8)}"},
// %T
{"%T", (4 - 3i), "complex128"},
}
func TestCountMallocs(t *testing.T) {
+ if testing.Short() {
+ return
+ }
+ runtime.UpdateMemStats()
mallocs := 0 - runtime.MemStats.Mallocs
for i := 0; i < 100; i++ {
Sprintf("")
}
+ runtime.UpdateMemStats()
mallocs += runtime.MemStats.Mallocs
Printf("mallocs per Sprintf(\"\"): %d\n", mallocs/100)
+ runtime.UpdateMemStats()
mallocs = 0 - runtime.MemStats.Mallocs
for i := 0; i < 100; i++ {
Sprintf("xxx")
}
+ runtime.UpdateMemStats()
mallocs += runtime.MemStats.Mallocs
Printf("mallocs per Sprintf(\"xxx\"): %d\n", mallocs/100)
+ runtime.UpdateMemStats()
mallocs = 0 - runtime.MemStats.Mallocs
for i := 0; i < 100; i++ {
Sprintf("%x", i)
}
+ runtime.UpdateMemStats()
mallocs += runtime.MemStats.Mallocs
Printf("mallocs per Sprintf(\"%%x\"): %d\n", mallocs/100)
+ runtime.UpdateMemStats()
+ mallocs = 0 - runtime.MemStats.Mallocs
+ for i := 0; i < 100; i++ {
+ Sprintf("%s", "hello")
+ }
+ runtime.UpdateMemStats()
+ mallocs += runtime.MemStats.Mallocs
+ Printf("mallocs per Sprintf(\"%%s\"): %d\n", mallocs/100)
+ runtime.UpdateMemStats()
mallocs = 0 - runtime.MemStats.Mallocs
for i := 0; i < 100; i++ {
Sprintf("%x %x", i, i)
}
+ runtime.UpdateMemStats()
mallocs += runtime.MemStats.Mallocs
Printf("mallocs per Sprintf(\"%%x %%x\"): %d\n", mallocs/100)
+ buf := new(bytes.Buffer)
+ runtime.UpdateMemStats()
+ mallocs = 0 - runtime.MemStats.Mallocs
+ for i := 0; i < 100; i++ {
+ buf.Reset()
+ Fprintf(buf, "%x %x %x", i, i, i)
+ }
+ runtime.UpdateMemStats()
+ mallocs += runtime.MemStats.Mallocs
+ Printf("mallocs per Fprintf(buf, \"%%x %%x %%x\"): %d\n", mallocs/100)
+ runtime.UpdateMemStats()
+ mallocs = 0 - runtime.MemStats.Mallocs
+ for i := 0; i < 100; i++ {
+ buf.Reset()
+ Fprintf(buf, "%s", "hello")
+ }
+ runtime.UpdateMemStats()
+ mallocs += runtime.MemStats.Mallocs
+ Printf("mallocs per Fprintf(buf, \"%%s\"): %d\n", mallocs/100)
}
type flagPrinter struct{}
}
}
-
// Check Formatter with Sprint, Sprintln, Sprintf
func TestFormatterPrintln(t *testing.T) {
f := F(1)
}
}
}
+
+// A type that panics in String.
+type Panic struct {
+ message interface{}
+}
+
+// Value receiver.
+func (p Panic) GoString() string {
+ panic(p.message)
+}
+
+// Value receiver.
+func (p Panic) String() string {
+ panic(p.message)
+}
+
+// A type that panics in Format.
+type PanicF struct {
+ message interface{}
+}
+
+// Value receiver.
+func (p PanicF) Format(f State, c int) {
+ panic(p.message)
+}
+
+var panictests = []struct {
+ fmt string
+ in interface{}
+ out string
+}{
+ // String
+ {"%d", (*Panic)(nil), "<nil>"}, // nil pointer special case
+ {"%d", Panic{io.ErrUnexpectedEOF}, "%d(PANIC=unexpected EOF)"},
+ {"%d", Panic{3}, "%d(PANIC=3)"},
+ // GoString
+ {"%#v", (*Panic)(nil), "<nil>"}, // nil pointer special case
+ {"%#v", Panic{io.ErrUnexpectedEOF}, "%v(PANIC=unexpected EOF)"},
+ {"%#v", Panic{3}, "%v(PANIC=3)"},
+ // Format
+ {"%s", (*PanicF)(nil), "<nil>"}, // nil pointer special case
+ {"%s", PanicF{io.ErrUnexpectedEOF}, "%s(PANIC=unexpected EOF)"},
+ {"%s", PanicF{3}, "%s(PANIC=3)"},
+}
+
+func TestPanics(t *testing.T) {
+ for _, tt := range panictests {
+ s := Sprintf(tt.fmt, tt.in)
+ if s != tt.out {
+ t.Errorf("%q: got %q expected %q", tt.fmt, s, tt.out)
+ }
+ }
+}