diff options
Diffstat (limited to 'src/pkg/fmt/fmt_test.go')
-rw-r--r-- | src/pkg/fmt/fmt_test.go | 107 |
1 files changed, 82 insertions, 25 deletions
diff --git a/src/pkg/fmt/fmt_test.go b/src/pkg/fmt/fmt_test.go index de0342967..af4b5c8f8 100644 --- a/src/pkg/fmt/fmt_test.go +++ b/src/pkg/fmt/fmt_test.go @@ -9,7 +9,6 @@ import ( . "fmt" "io" "math" - "runtime" // for the malloc count test only "strings" "testing" "time" @@ -96,7 +95,7 @@ type SI struct { I interface{} } -// A type with a String method with pointer receiver for testing %p +// P is a type with a String method with pointer receiver for testing %p. type P int var pValue P @@ -105,6 +104,9 @@ func (p *P) String() string { return "String(p)" } +var barray = [5]renamedUint8{1, 2, 3, 4, 5} +var bslice = barray[:] + var b byte var fmttests = []struct { @@ -127,6 +129,10 @@ var fmttests = []struct { {"%s", []byte("abc"), "abc"}, {"%x", []byte("abc"), "616263"}, {"% x", []byte("abc\xff"), "61 62 63 ff"}, + {"%#x", []byte("abc\xff"), "0x610x620x630xff"}, + {"%#X", []byte("abc\xff"), "0X610X620X630XFF"}, + {"%# x", []byte("abc\xff"), "0x61 0x62 0x63 0xff"}, + {"%# X", []byte("abc\xff"), "0X61 0X62 0X63 0XFF"}, {"% X", []byte("abc\xff"), "61 62 63 FF"}, {"%x", []byte("xyz"), "78797a"}, {"%X", []byte("xyz"), "78797A"}, @@ -172,6 +178,8 @@ var fmttests = []struct { {"%.3q", "日本語日本語", `"日本語"`}, {"%.3q", []byte("日本語日本語"), `"日本語"`}, {"%10.1q", "日本語日本語", ` "日"`}, + {"%10v", nil, " <nil>"}, + {"%-10v", nil, "<nil> "}, // integers {"%d", 12345, "12345"}, @@ -328,14 +336,18 @@ var fmttests = []struct { // arrays {"%v", array, "[1 2 3 4 5]"}, {"%v", iarray, "[1 hello 2.5 <nil>]"}, + {"%v", barray, "[1 2 3 4 5]"}, {"%v", &array, "&[1 2 3 4 5]"}, {"%v", &iarray, "&[1 hello 2.5 <nil>]"}, + {"%v", &barray, "&[1 2 3 4 5]"}, // slices {"%v", slice, "[1 2 3 4 5]"}, {"%v", islice, "[1 hello 2.5 <nil>]"}, + {"%v", bslice, "[1 2 3 4 5]"}, {"%v", &slice, "&[1 2 3 4 5]"}, {"%v", &islice, "&[1 hello 2.5 <nil>]"}, + {"%v", &bslice, "&[1 2 3 4 5]"}, // complexes with %v {"%v", 1 + 2i, "(1+2i)"}, @@ -350,10 +362,12 @@ var fmttests = []struct { {"%+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 + // other formats on Stringable items {"%s", I(23), `<23>`}, {"%q", I(23), `"<23>"`}, {"%x", I(23), `3c32333e`}, + {"%#x", I(23), `0x3c0x320x330x3e`}, + {"%# x", I(23), `0x3c 0x32 0x33 0x3e`}, {"%d", I(23), `23`}, // Stringer applies only to string formats. // go syntax @@ -375,6 +389,9 @@ var fmttests = []struct { {"%#v", &iarray, `&[4]interface {}{1, "hello", 2.5, interface {}(nil)}`}, {"%#v", map[int]byte(nil), `map[int]uint8(nil)`}, {"%#v", map[int]byte{}, `map[int]uint8{}`}, + {"%#v", "foo", `"foo"`}, + {"%#v", barray, `[5]fmt_test.renamedUint8{0x1, 0x2, 0x3, 0x4, 0x5}`}, + {"%#v", bslice, `[]fmt_test.renamedUint8{0x1, 0x2, 0x3, 0x4, 0x5}`}, // slices with other formats {"%#x", []int{1, 2, 15}, `[0x1 0x2 0xf]`}, @@ -400,6 +417,9 @@ var fmttests = []struct { {"%x", renamedString("thing"), "7468696e67"}, {"%d", renamedBytes([]byte{1, 2, 15}), `[1 2 15]`}, {"%q", renamedBytes([]byte("hello")), `"hello"`}, + {"%x", []renamedUint8{'a', 'b', 'c'}, "616263"}, + {"%s", []renamedUint8{'h', 'e', 'l', 'l', 'o'}, "hello"}, + {"%q", []renamedUint8{'h', 'e', 'l', 'l', 'o'}, `"hello"`}, {"%v", renamedFloat32(22), "22"}, {"%v", renamedFloat64(33), "33"}, {"%v", renamedComplex64(3 + 4i), "(3+4i)"}, @@ -419,6 +439,8 @@ var fmttests = []struct { {"%T", renamedComplex128(4 - 3i), "fmt_test.renamedComplex128"}, {"%T", intVal, "int"}, {"%6T", &intVal, " *int"}, + {"%10T", nil, " <nil>"}, + {"%-10T", nil, "<nil> "}, // %p {"p0=%p", new(int), "p0=0xPTR"}, @@ -441,6 +463,11 @@ var fmttests = []struct { {"%v", (*int)(nil), "<nil>"}, {"%v", new(int), "0xPTR"}, + // %d etc. pointers use specified base. + {"%d", new(int), "PTR_d"}, + {"%o", new(int), "PTR_o"}, + {"%x", new(int), "PTR_x"}, + // %d on Stringer should give integer if possible {"%s", time.Time{}.Month(), "January"}, {"%d", time.Time{}.Month(), "1"}, @@ -464,20 +491,37 @@ var fmttests = []struct { // Used to crash because nByte didn't allow for a sign. {"%b", int64(-1 << 63), "-1000000000000000000000000000000000000000000000000000000000000000"}, + + // Complex fmt used to leave the plus flag set for future entries in the array + // causing +2+0i and +3+0i instead of 2+0i and 3+0i. + {"%v", []complex64{1, 2, 3}, "[(1+0i) (2+0i) (3+0i)]"}, + {"%v", []complex128{1, 2, 3}, "[(1+0i) (2+0i) (3+0i)]"}, } func TestSprintf(t *testing.T) { for _, tt := range fmttests { s := Sprintf(tt.fmt, tt.val) if i := strings.Index(tt.out, "PTR"); i >= 0 { + pattern := "PTR" + chars := "0123456789abcdefABCDEF" + switch { + case strings.HasPrefix(tt.out[i:], "PTR_d"): + pattern = "PTR_d" + chars = chars[:10] + case strings.HasPrefix(tt.out[i:], "PTR_o"): + pattern = "PTR_o" + chars = chars[:8] + case strings.HasPrefix(tt.out[i:], "PTR_x"): + pattern = "PTR_x" + } j := i for ; j < len(s); j++ { c := s[j] - if (c < '0' || c > '9') && (c < 'a' || c > 'f') && (c < 'A' || c > 'F') { + if !strings.ContainsRune(chars, rune(c)) { break } } - s = s[0:i] + "PTR" + s[j:] + s = s[0:i] + pattern + s[j:] } if s != tt.out { if _, ok := tt.val.(string); ok { @@ -527,6 +571,14 @@ func BenchmarkSprintfFloat(b *testing.B) { } } +func BenchmarkManyArgs(b *testing.B) { + var buf bytes.Buffer + for i := 0; i < b.N; i++ { + buf.Reset() + Fprintf(&buf, "%2d/%2d/%2d %d:%d:%d %s %s\n", 3, 4, 5, 11, 12, 13, "hello", "world") + } +} + var mallocBuf bytes.Buffer var mallocTest = []struct { @@ -550,17 +602,9 @@ var _ bytes.Buffer func TestCountMallocs(t *testing.T) { for _, mt := range mallocTest { - const N = 100 - memstats := new(runtime.MemStats) - runtime.ReadMemStats(memstats) - mallocs := 0 - memstats.Mallocs - for i := 0; i < N; i++ { - mt.fn() - } - runtime.ReadMemStats(memstats) - mallocs += memstats.Mallocs - if mallocs/N > uint64(mt.count) { - t.Errorf("%s: expected %d mallocs, got %d", mt.desc, mt.count, mallocs/N) + mallocs := testing.AllocsPerRun(100, mt.fn) + if got, max := mallocs, float64(mt.count); got > max { + t.Errorf("%s: got %v allocs, want <=%v", mt.desc, got, max) } } } @@ -636,7 +680,8 @@ func TestStructPrinter(t *testing.T) { } } -// Check map printing using substrings so we don't depend on the print order. +// presentInMap checks map printing using substrings so we don't depend on the +// print order. func presentInMap(s string, a []string, t *testing.T) { for i := 0; i < len(a); i++ { loc := strings.Index(s, a[i]) @@ -677,8 +722,8 @@ func TestEmptyMap(t *testing.T) { } } -// Check that Sprint (and hence Print, Fprint) puts spaces in the right places, -// that is, between arg pairs in which neither is a string. +// TestBlank checks that Sprint (and hence Print, Fprint) puts spaces in the +// right places, that is, between arg pairs in which neither is a string. func TestBlank(t *testing.T) { got := Sprint("<", 1, ">:", 1, 2, 3, "!") expect := "<1>:1 2 3!" @@ -687,8 +732,8 @@ func TestBlank(t *testing.T) { } } -// Check that Sprintln (and hence Println, Fprintln) puts spaces in the right places, -// that is, between all arg pairs. +// TestBlankln checks that Sprintln (and hence Println, Fprintln) puts spaces in +// the right places, that is, between all arg pairs. func TestBlankln(t *testing.T) { got := Sprintln("<", 1, ">:", 1, 2, 3, "!") expect := "< 1 >: 1 2 3 !\n" @@ -697,7 +742,7 @@ func TestBlankln(t *testing.T) { } } -// Check Formatter with Sprint, Sprintln, Sprintf +// TestFormatterPrintln checks Formatter with Sprint, Sprintln, Sprintf. func TestFormatterPrintln(t *testing.T) { f := F(1) expect := "<v=F(1)>\n" @@ -746,7 +791,7 @@ func TestWidthAndPrecision(t *testing.T) { } } -// A type that panics in String. +// Panic is a type that panics in String. type Panic struct { message interface{} } @@ -761,7 +806,7 @@ func (p Panic) String() string { panic(p.message) } -// A type that panics in Format. +// PanicF is a type that panics in Format. type PanicF struct { message interface{} } @@ -799,7 +844,7 @@ func TestPanics(t *testing.T) { } } -// Test that erroneous String routine doesn't cause fatal recursion. +// recurCount tests that erroneous String routine doesn't cause fatal recursion. var recurCount = 0 type Recur struct { @@ -842,3 +887,15 @@ func TestIsSpace(t *testing.T) { } } } + +func TestNilDoesNotBecomeTyped(t *testing.T) { + type A struct{} + type B struct{} + var a *A = nil + var b B = B{} + got := Sprintf("%s %s %s %s %s", nil, a, nil, b, nil) + const expect = "%!s(<nil>) %!s(*fmt_test.A=<nil>) %!s(<nil>) {} %!s(<nil>)" + if got != expect { + t.Errorf("expected:\n\t%q\ngot:\n\t%q", expect, got) + } +} |