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.
14 func check(t *testing.T, b *Builder, want string) {
18 t.Errorf("String: got %#q; want %#q", got, want)
21 if n := b.Len(); n != len(got) {
22 t.Errorf("Len: got %d; but len(String()) is %d", n, len(got))
24 if n := b.Cap(); n < len(got) {
25 t.Errorf("Cap: got %d; but len(String()) is %d", n, len(got))
29 func TestBuilder(t *testing.T) {
32 n, err := b.WriteString("hello")
33 if err != nil || n != 5 {
34 t.Errorf("WriteString: got %d,%s; want 5,nil", n, err)
37 if err = b.WriteByte(' '); err != nil {
38 t.Errorf("WriteByte: %s", err)
40 check(t, &b, "hello ")
41 n, err = b.WriteString("world")
42 if err != nil || n != 5 {
43 t.Errorf("WriteString: got %d,%s; want 5,nil", n, err)
45 check(t, &b, "hello world")
48 func TestBuilderString(t *testing.T) {
50 b.WriteString("alpha")
54 check(t, &b, "alphabeta")
56 b.WriteString("gamma")
57 check(t, &b, "alphabetagamma")
60 // Check that subsequent operations didn't change the returned strings.
61 if want := "alpha"; s1 != want {
62 t.Errorf("first String result is now %q; want %q", s1, want)
64 if want := "alphabeta"; s2 != want {
65 t.Errorf("second String result is now %q; want %q", s2, want)
67 if want := "alphabetagamma"; s3 != want {
68 t.Errorf("third String result is now %q; want %q", s3, want)
72 func TestBuilderReset(t *testing.T) {
81 // Ensure that writing after Reset doesn't alter
82 // previously returned strings.
85 if want := "aaa"; s != want {
86 t.Errorf("previous String result changed after Reset: got %q; want %q", s, want)
90 func TestBuilderGrow(t *testing.T) {
91 if runtime.Compiler == "gccgo" {
92 t.Skip("skip for gccgo until escape analysis improves")
94 for _, growLen := range []int{0, 100, 1000, 10000, 100000} {
95 p := bytes.Repeat([]byte{'a'}, growLen)
96 allocs := testing.AllocsPerRun(100, func() {
98 b.Grow(growLen) // should be only alloc, when growLen > 0
99 if b.Cap() < growLen {
100 t.Fatalf("growLen=%d: Cap() is lower than growLen", growLen)
103 if b.String() != string(p) {
104 t.Fatalf("growLen=%d: bad data written after Grow", growLen)
111 if g, w := int(allocs), wantAllocs; g != w {
112 t.Errorf("growLen=%d: got %d allocs during Write; want %v", growLen, g, w)
117 func TestBuilderWrite2(t *testing.T) {
118 const s0 = "hello 世界"
119 for _, tt := range []struct {
121 fn func(b *Builder) (int, error)
127 func(b *Builder) (int, error) { return b.Write([]byte(s0)) },
133 func(b *Builder) (int, error) { return b.WriteRune('a') },
139 func(b *Builder) (int, error) { return b.WriteRune('世') },
145 func(b *Builder) (int, error) { return b.WriteString(s0) },
150 t.Run(tt.name, func(t *testing.T) {
154 t.Fatalf("first call: got %s", err)
157 t.Errorf("first call: got n=%d; want %d", n, tt.n)
159 check(t, &b, tt.want)
163 t.Fatalf("second call: got %s", err)
166 t.Errorf("second call: got n=%d; want %d", n, tt.n)
168 check(t, &b, tt.want+tt.want)
173 func TestBuilderWriteByte(t *testing.T) {
175 if err := b.WriteByte('a'); err != nil {
178 if err := b.WriteByte(0); err != nil {
181 check(t, &b, "a\x00")
184 func TestBuilderAllocs(t *testing.T) {
185 if runtime.Compiler == "gccgo" {
186 t.Skip("skip for gccgo until escape analysis improves")
188 // Issue 23382; verify that copyCheck doesn't force the
189 // Builder to escape and be heap allocated.
190 n := testing.AllocsPerRun(10000, func() {
193 b.WriteString("abcde")
197 t.Errorf("Builder allocs = %v; want 1", n)
201 func TestBuilderCopyPanic(t *testing.T) {
214 _ = b.String() // appease vet
299 for _, tt := range tests {
300 didPanic := make(chan bool)
302 defer func() { didPanic <- recover() != nil }()
305 if got := <-didPanic; got != tt.wantPanic {
306 t.Errorf("%s: panicked = %v; want %v", tt.name, got, tt.wantPanic)
311 var someBytes = []byte("some bytes sdljlk jsklj3lkjlk djlkjw")
315 func benchmarkBuilder(b *testing.B, f func(b *testing.B, numWrite int, grow bool)) {
316 b.Run("1Write_NoGrow", func(b *testing.B) {
320 b.Run("3Write_NoGrow", func(b *testing.B) {
324 b.Run("3Write_Grow", func(b *testing.B) {
330 func BenchmarkBuildString_Builder(b *testing.B) {
331 benchmarkBuilder(b, func(b *testing.B, numWrite int, grow bool) {
332 for i := 0; i < b.N; i++ {
335 buf.Grow(len(someBytes) * numWrite)
337 for i := 0; i < numWrite; i++ {
345 func BenchmarkBuildString_ByteBuffer(b *testing.B) {
346 benchmarkBuilder(b, func(b *testing.B, numWrite int, grow bool) {
347 for i := 0; i < b.N; i++ {
350 buf.Grow(len(someBytes) * numWrite)
352 for i := 0; i < numWrite; i++ {