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.
15 func check(t
*testing
.T
, b
*Builder
, want
string) {
19 t
.Errorf("String: got %#q; want %#q", got
, want
)
22 if n
:= b
.Len(); n
!= len(got
) {
23 t
.Errorf("Len: got %d; but len(String()) is %d", n
, len(got
))
25 if n
:= b
.Cap(); n
< len(got
) {
26 t
.Errorf("Cap: got %d; but len(String()) is %d", n
, len(got
))
30 func TestBuilder(t
*testing
.T
) {
33 n
, err
:= b
.WriteString("hello")
34 if err
!= nil || n
!= 5 {
35 t
.Errorf("WriteString: got %d,%s; want 5,nil", n
, err
)
38 if err
= b
.WriteByte(' '); err
!= nil {
39 t
.Errorf("WriteByte: %s", err
)
41 check(t
, &b
, "hello ")
42 n
, err
= b
.WriteString("world")
43 if err
!= nil || n
!= 5 {
44 t
.Errorf("WriteString: got %d,%s; want 5,nil", n
, err
)
46 check(t
, &b
, "hello world")
49 func TestBuilderString(t
*testing
.T
) {
51 b
.WriteString("alpha")
55 check(t
, &b
, "alphabeta")
57 b
.WriteString("gamma")
58 check(t
, &b
, "alphabetagamma")
61 // Check that subsequent operations didn't change the returned strings.
62 if want
:= "alpha"; s1
!= want
{
63 t
.Errorf("first String result is now %q; want %q", s1
, want
)
65 if want
:= "alphabeta"; s2
!= want
{
66 t
.Errorf("second String result is now %q; want %q", s2
, want
)
68 if want
:= "alphabetagamma"; s3
!= want
{
69 t
.Errorf("third String result is now %q; want %q", s3
, want
)
73 func TestBuilderReset(t
*testing
.T
) {
82 // Ensure that writing after Reset doesn't alter
83 // previously returned strings.
86 if want
:= "aaa"; s
!= want
{
87 t
.Errorf("previous String result changed after Reset: got %q; want %q", s
, want
)
91 func TestBuilderGrow(t
*testing
.T
) {
92 if runtime
.Compiler
== "gccgo" {
93 t
.Skip("skip for gccgo until escape analysis improves")
95 for _
, growLen
:= range []int{0, 100, 1000, 10000, 100000} {
96 p
:= bytes
.Repeat([]byte{'a'}, growLen
)
97 allocs
:= testing
.AllocsPerRun(100, func() {
99 b
.Grow(growLen
) // should be only alloc, when growLen > 0
100 if b
.Cap() < growLen
{
101 t
.Fatalf("growLen=%d: Cap() is lower than growLen", growLen
)
104 if b
.String() != string(p
) {
105 t
.Fatalf("growLen=%d: bad data written after Grow", growLen
)
112 if g
, w
:= int(allocs
), wantAllocs
; g
!= w
{
113 t
.Errorf("growLen=%d: got %d allocs during Write; want %v", growLen
, g
, w
)
118 func TestBuilderWrite2(t
*testing
.T
) {
119 const s0
= "hello 世界"
120 for _
, tt
:= range []struct {
122 fn
func(b
*Builder
) (int, error
)
128 func(b
*Builder
) (int, error
) { return b
.Write([]byte(s0
)) },
134 func(b
*Builder
) (int, error
) { return b
.WriteRune('a') },
140 func(b
*Builder
) (int, error
) { return b
.WriteRune('世') },
146 func(b
*Builder
) (int, error
) { return b
.WriteString(s0
) },
151 t
.Run(tt
.name
, func(t
*testing
.T
) {
155 t
.Fatalf("first call: got %s", err
)
158 t
.Errorf("first call: got n=%d; want %d", n
, tt
.n
)
160 check(t
, &b
, tt
.want
)
164 t
.Fatalf("second call: got %s", err
)
167 t
.Errorf("second call: got n=%d; want %d", n
, tt
.n
)
169 check(t
, &b
, tt
.want
+tt
.want
)
174 func TestBuilderWriteByte(t
*testing
.T
) {
176 if err
:= b
.WriteByte('a'); err
!= nil {
179 if err
:= b
.WriteByte(0); err
!= nil {
182 check(t
, &b
, "a\x00")
185 func TestBuilderAllocs(t
*testing
.T
) {
186 if runtime
.Compiler
== "gccgo" {
187 t
.Skip("skip for gccgo until escape analysis improves")
189 // Issue 23382; verify that copyCheck doesn't force the
190 // Builder to escape and be heap allocated.
191 n
:= testing
.AllocsPerRun(10000, func() {
194 b
.WriteString("abcde")
198 t
.Errorf("Builder allocs = %v; want 1", n
)
202 func TestBuilderCopyPanic(t
*testing
.T
) {
215 _
= b
.String() // appease vet
300 for _
, tt
:= range tests
{
301 didPanic
:= make(chan bool)
303 defer func() { didPanic
<- recover() != nil }()
306 if got
:= <-didPanic
; got
!= tt
.wantPanic
{
307 t
.Errorf("%s: panicked = %v; want %v", tt
.name
, got
, tt
.wantPanic
)
312 func TestBuilderWriteInvalidRune(t
*testing
.T
) {
313 // Invalid runes, including negative ones, should be written as
315 for _
, r
:= range []rune
{-1, utf8
.MaxRune
+ 1} {
318 check(t
, &b
, "\uFFFD")
322 var someBytes
= []byte("some bytes sdljlk jsklj3lkjlk djlkjw")
326 func benchmarkBuilder(b
*testing
.B
, f
func(b
*testing
.B
, numWrite
int, grow
bool)) {
327 b
.Run("1Write_NoGrow", func(b
*testing
.B
) {
331 b
.Run("3Write_NoGrow", func(b
*testing
.B
) {
335 b
.Run("3Write_Grow", func(b
*testing
.B
) {
341 func BenchmarkBuildString_Builder(b
*testing
.B
) {
342 benchmarkBuilder(b
, func(b
*testing
.B
, numWrite
int, grow
bool) {
343 for i
:= 0; i
< b
.N
; i
++ {
346 buf
.Grow(len(someBytes
) * numWrite
)
348 for i
:= 0; i
< numWrite
; i
++ {
356 func BenchmarkBuildString_ByteBuffer(b
*testing
.B
) {
357 benchmarkBuilder(b
, func(b
*testing
.B
, numWrite
int, grow
bool) {
358 for i
:= 0; i
< b
.N
; i
++ {
361 buf
.Grow(len(someBytes
) * numWrite
)
363 for i
:= 0; i
< numWrite
; i
++ {