package cache
import (
"bytes"
"sync"
. "gopkg.in/check.v1"
)
type BufferSuite struct {
c map[string]Buffer
aBuffer []byte
bBuffer []byte
cBuffer []byte
dBuffer []byte
eBuffer []byte
}
var _ = Suite(&BufferSuite{})
func (s *BufferSuite) SetUpTest(c *C) {
s.aBuffer = []byte("a")
s.bBuffer = []byte("bbb")
s.cBuffer = []byte("c")
s.dBuffer = []byte("d")
s.eBuffer = []byte("ee")
s.c = make(map[string]Buffer)
s.c["two_bytes"] = NewBufferLRU(2 * Byte)
s.c["default_lru"] = NewBufferLRUDefault()
}
func (s *BufferSuite) TestPutSameBuffer(c *C) {
for _, o := range s.c {
o.Put(1, s.aBuffer)
o.Put(1, s.aBuffer)
_, ok := o.Get(1)
c.Assert(ok, Equals, true)
}
}
func (s *ObjectSuite) TestPutSameBufferWithDifferentSize(c *C) {
aBuffer := []byte("a")
bBuffer := []byte("bbb")
cBuffer := []byte("ccccc")
dBuffer := []byte("ddddddd")
cache := NewBufferLRU(7 * Byte)
cache.Put(1, aBuffer)
cache.Put(1, bBuffer)
cache.Put(1, cBuffer)
cache.Put(1, dBuffer)
c.Assert(cache.MaxSize, Equals, 7*Byte)
c.Assert(cache.actualSize, Equals, 7*Byte)
c.Assert(cache.ll.Len(), Equals, 1)
buf, ok := cache.Get(1)
c.Assert(bytes.Equal(buf, dBuffer), Equals, true)
c.Assert(FileSize(len(buf)), Equals, 7*Byte)
c.Assert(ok, Equals, true)
}
func (s *BufferSuite) TestPutBigBuffer(c *C) {
for _, o := range s.c {
o.Put(1, s.bBuffer)
_, ok := o.Get(2)
c.Assert(ok, Equals, false)
}
}
func (s *BufferSuite) TestPutCacheOverflow(c *C) {
// this test only works with an specific size
o := s.c["two_bytes"]
o.Put(1, s.aBuffer)
o.Put(2, s.cBuffer)
o.Put(3, s.dBuffer)
obj, ok := o.Get(1)
c.Assert(ok, Equals, false)
c.Assert(obj, IsNil)
obj, ok = o.Get(2)
c.Assert(ok, Equals, true)
c.Assert(obj, NotNil)
obj, ok = o.Get(3)
c.Assert(ok, Equals, true)
c.Assert(obj, NotNil)
}
func (s *BufferSuite) TestEvictMultipleBuffers(c *C) {
o := s.c["two_bytes"]
o.Put(1, s.cBuffer)
o.Put(2, s.dBuffer) // now cache is full with two objects
o.Put(3, s.eBuffer) // this put should evict all previous objects
obj, ok := o.Get(1)
c.Assert(ok, Equals, false)
c.Assert(obj, IsNil)
obj, ok = o.Get(2)
c.Assert(ok, Equals, false)
c.Assert(obj, IsNil)
obj, ok = o.Get(3)
c.Assert(ok, Equals, true)
c.Assert(obj, NotNil)
}
func (s *BufferSuite) TestClear(c *C) {
for _, o := range s.c {
o.Put(1, s.aBuffer)
o.Clear()
obj, ok := o.Get(1)
c.Assert(ok, Equals, false)
c.Assert(obj, IsNil)
}
}
func (s *BufferSuite) TestConcurrentAccess(c *C) {
for _, o := range s.c {
var wg sync.WaitGroup
for i := 0; i < 1000; i++ {
wg.Add(3)
go func(i int) {
o.Put(int64(i), []byte{00})
wg.Done()
}(i)
go func(i int) {
if i%30 == 0 {
o.Clear()
}
wg.Done()
}(i)
go func(i int) {
o.Get(int64(i))
wg.Done()
}(i)
}
wg.Wait()
}
}
func (s *BufferSuite) TestDefaultLRU(c *C) {
defaultLRU := s.c["default_lru"].(*BufferLRU)
c.Assert(defaultLRU.MaxSize, Equals, DefaultMaxSize)
}