Browse Source

Merge pull request #149 from vmarkovtsev/master

Add the tests for hibernation
Vadim Markovtsev 6 years ago
parent
commit
ee0d356ec4
3 changed files with 66 additions and 1 deletions
  1. 16 1
      internal/rbtree/rbtree.go
  2. 39 0
      internal/rbtree/rbtree_test.go
  3. 11 0
      version_test.go

+ 16 - 1
internal/rbtree/rbtree.go

@@ -40,11 +40,17 @@ func (allocator Allocator) Size() int {
 
 // Used returns the number of nodes contained in the allocator.
 func (allocator Allocator) Used() int {
+	if allocator.storage == nil {
+		panic("hibernated allocators cannot be used")
+	}
 	return len(allocator.storage) - len(allocator.gaps)
 }
 
 // Clone copies an existing RBTree allocator.
 func (allocator *Allocator) Clone() *Allocator {
+	if allocator.storage == nil {
+		panic("cannot clone a hibernated allocator")
+	}
 	newAllocator := &Allocator{
 		storage: make([]node, len(allocator.storage), cap(allocator.storage)),
 		gaps:    map[uint32]bool{},
@@ -58,10 +64,13 @@ func (allocator *Allocator) Clone() *Allocator {
 
 // Hibernate compresses the allocated memory.
 func (allocator *Allocator) Hibernate() {
-	if allocator.HibernationThreshold == 0 || len(allocator.storage) < allocator.HibernationThreshold {
+	if allocator.HibernationThreshold > 0 && len(allocator.storage) < allocator.HibernationThreshold {
 		return
 	}
 	allocator.hibernatedLen = len(allocator.storage)
+	if allocator.hibernatedLen == 0 {
+		return
+	}
 	buffers := [6][]uint32{}
 	for i := 0; i < len(buffers); i++ {
 		buffers[i] = make([]uint32, len(allocator.storage))
@@ -122,6 +131,9 @@ func (allocator *Allocator) Boot() {
 }
 
 func (allocator *Allocator) malloc() uint32 {
+	if allocator.storage == nil {
+		panic("hibernated allocators cannot be used")
+	}
 	if len(allocator.gaps) > 0 {
 		var key uint32
 		for key = range allocator.gaps {
@@ -146,6 +158,9 @@ func (allocator *Allocator) malloc() uint32 {
 }
 
 func (allocator *Allocator) free(n uint32) {
+	if allocator.storage == nil {
+		panic("hibernated allocators cannot be used")
+	}
 	_, exists := allocator.gaps[n]
 	doAssert(!exists)
 	allocator.storage[n] = node{}

+ 39 - 0
internal/rbtree/rbtree_test.go

@@ -380,3 +380,42 @@ func TestErase(t *testing.T) {
 	assert.Equal(t, alloc.Used(), 1)
 	assert.Equal(t, alloc.Size(), 11)
 }
+
+func TestAllocatorHibernateBoot(t *testing.T) {
+	alloc := NewAllocator()
+	for i := 0; i < 10000; i++ {
+		n := alloc.malloc()
+		alloc.storage[n].item.Key = uint32(i)
+		alloc.storage[n].item.Value = uint32(i)
+		alloc.storage[n].left = uint32(i)
+		alloc.storage[n].right = uint32(i)
+		alloc.storage[n].parent = uint32(i)
+		alloc.storage[n].color = i%2 == 0
+	}
+	alloc.Hibernate()
+	assert.Nil(t, alloc.storage)
+	assert.Equal(t, alloc.Size(), 0)
+	assert.Equal(t, alloc.hibernatedLen, 10001)
+	assert.PanicsWithValue(t, "hibernated allocators cannot be used", func() { alloc.Used() })
+	assert.PanicsWithValue(t, "hibernated allocators cannot be used", func() { alloc.malloc() })
+	assert.PanicsWithValue(t, "hibernated allocators cannot be used", func() { alloc.free(0) })
+	assert.PanicsWithValue(t, "cannot clone a hibernated allocator", func() { alloc.Clone() })
+	alloc.Boot()
+	assert.Equal(t, alloc.hibernatedLen, 0)
+	for n := 1; n <= 10000; n++ {
+		assert.Equal(t, alloc.storage[n].item.Key, uint32(n-1))
+		assert.Equal(t, alloc.storage[n].item.Value, uint32(n-1))
+		assert.Equal(t, alloc.storage[n].left, uint32(n-1))
+		assert.Equal(t, alloc.storage[n].right, uint32(n-1))
+		assert.Equal(t, alloc.storage[n].parent, uint32(n-1))
+		assert.Equal(t, alloc.storage[n].color, (n-1)%2 == 0)
+	}
+}
+
+func TestAllocatorHibernateBootEmpty(t *testing.T) {
+	alloc := NewAllocator()
+	alloc.Hibernate()
+	alloc.Boot()
+	assert.Equal(t, alloc.Size(), 0)
+	assert.Equal(t, alloc.Used(), 0)
+}

+ 11 - 0
version_test.go

@@ -0,0 +1,11 @@
+package hercules
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestVersion(t *testing.T) {
+	assert.Equal(t, BinaryVersion, 6)
+}