1package bytebufferpool
2
3import (
4	"math/rand"
5	"testing"
6	"time"
7)
8
9func TestIndex(t *testing.T) {
10	testIndex(t, 0, 0)
11	testIndex(t, 1, 0)
12
13	testIndex(t, minSize-1, 0)
14	testIndex(t, minSize, 0)
15	testIndex(t, minSize+1, 1)
16
17	testIndex(t, 2*minSize-1, 1)
18	testIndex(t, 2*minSize, 1)
19	testIndex(t, 2*minSize+1, 2)
20
21	testIndex(t, maxSize-1, steps-1)
22	testIndex(t, maxSize, steps-1)
23	testIndex(t, maxSize+1, steps-1)
24}
25
26func testIndex(t *testing.T, n, expectedIdx int) {
27	idx := index(n)
28	if idx != expectedIdx {
29		t.Fatalf("unexpected idx for n=%d: %d. Expecting %d", n, idx, expectedIdx)
30	}
31}
32
33func TestPoolCalibrate(t *testing.T) {
34	for i := 0; i < steps*calibrateCallsThreshold; i++ {
35		n := 1004
36		if i%15 == 0 {
37			n = rand.Intn(15234)
38		}
39		testGetPut(t, n)
40	}
41}
42
43func TestPoolVariousSizesSerial(t *testing.T) {
44	testPoolVariousSizes(t)
45}
46
47func TestPoolVariousSizesConcurrent(t *testing.T) {
48	concurrency := 5
49	ch := make(chan struct{})
50	for i := 0; i < concurrency; i++ {
51		go func() {
52			testPoolVariousSizes(t)
53			ch <- struct{}{}
54		}()
55	}
56	for i := 0; i < concurrency; i++ {
57		select {
58		case <-ch:
59		case <-time.After(3 * time.Second):
60			t.Fatalf("timeout")
61		}
62	}
63}
64
65func testPoolVariousSizes(t *testing.T) {
66	for i := 0; i < steps+1; i++ {
67		n := (1 << uint32(i))
68
69		testGetPut(t, n)
70		testGetPut(t, n+1)
71		testGetPut(t, n-1)
72
73		for j := 0; j < 10; j++ {
74			testGetPut(t, j+n)
75		}
76	}
77}
78
79func testGetPut(t *testing.T, n int) {
80	bb := Get()
81	if len(bb.B) > 0 {
82		t.Fatalf("non-empty byte buffer returned from acquire")
83	}
84	bb.B = allocNBytes(bb.B, n)
85	Put(bb)
86}
87
88func allocNBytes(dst []byte, n int) []byte {
89	diff := n - cap(dst)
90	if diff <= 0 {
91		return dst[:n]
92	}
93	return append(dst, make([]byte, diff)...)
94}
95