Merge branch '8288-arv-mount-deadlock' refs #8288
[arvados.git] / services / keepstore / bufferpool_test.go
1 package main
2
3 import (
4         . "gopkg.in/check.v1"
5         "time"
6 )
7
8 var _ = Suite(&BufferPoolSuite{})
9
10 type BufferPoolSuite struct{}
11
12 // Initialize a default-sized buffer pool for the benefit of test
13 // suites that don't run main().
14 func init() {
15         bufs = newBufferPool(maxBuffers, BlockSize)
16 }
17
18 // Restore sane default after bufferpool's own tests
19 func (s *BufferPoolSuite) TearDownTest(c *C) {
20         bufs = newBufferPool(maxBuffers, BlockSize)
21 }
22
23 func (s *BufferPoolSuite) TestBufferPoolBufSize(c *C) {
24         bufs := newBufferPool(2, 10)
25         b1 := bufs.Get(1)
26         bufs.Get(2)
27         bufs.Put(b1)
28         b3 := bufs.Get(3)
29         c.Check(len(b3), Equals, 3)
30 }
31
32 func (s *BufferPoolSuite) TestBufferPoolUnderLimit(c *C) {
33         bufs := newBufferPool(3, 10)
34         b1 := bufs.Get(10)
35         bufs.Get(10)
36         testBufferPoolRace(c, bufs, b1, "Get")
37 }
38
39 func (s *BufferPoolSuite) TestBufferPoolAtLimit(c *C) {
40         bufs := newBufferPool(2, 10)
41         b1 := bufs.Get(10)
42         bufs.Get(10)
43         testBufferPoolRace(c, bufs, b1, "Put")
44 }
45
46 func testBufferPoolRace(c *C, bufs *bufferPool, unused []byte, expectWin string) {
47         race := make(chan string)
48         go func() {
49                 bufs.Get(10)
50                 time.Sleep(time.Millisecond)
51                 race <- "Get"
52         }()
53         go func() {
54                 time.Sleep(10 * time.Millisecond)
55                 bufs.Put(unused)
56                 race <- "Put"
57         }()
58         c.Check(<-race, Equals, expectWin)
59         c.Check(<-race, Not(Equals), expectWin)
60         close(race)
61 }
62
63 func (s *BufferPoolSuite) TestBufferPoolReuse(c *C) {
64         bufs := newBufferPool(2, 10)
65         bufs.Get(10)
66         last := bufs.Get(10)
67         // The buffer pool is allowed to throw away unused buffers
68         // (e.g., during sync.Pool's garbage collection hook, in the
69         // the current implementation). However, if unused buffers are
70         // getting thrown away and reallocated more than {arbitrary
71         // frequency threshold} during a busy loop, it's not acting
72         // much like a buffer pool.
73         allocs := 1000
74         reuses := 0
75         for i := 0; i < allocs; i++ {
76                 bufs.Put(last)
77                 next := bufs.Get(10)
78                 copy(last, []byte("last"))
79                 copy(next, []byte("next"))
80                 if last[0] == 'n' {
81                         reuses++
82                 }
83                 last = next
84         }
85         c.Check(reuses > allocs*95/100, Equals, true)
86 }