bbolt/leaf_test.go

125 lines
3.9 KiB
Go

package bolt
import (
"testing"
"unsafe"
"github.com/stretchr/testify/assert"
)
// Ensure that a leaf can insert a key/value.
func TestLeafPut(t *testing.T) {
l := &leaf{items: make(leafItems, 0)}
l.put([]byte("baz"), []byte("2"))
l.put([]byte("foo"), []byte("0"))
l.put([]byte("bar"), []byte("1"))
l.put([]byte("foo"), []byte("3"))
assert.Equal(t, len(l.items), 3)
assert.Equal(t, l.items[0], leafItem{[]byte("bar"), []byte("1")})
assert.Equal(t, l.items[1], leafItem{[]byte("baz"), []byte("2")})
assert.Equal(t, l.items[2], leafItem{[]byte("foo"), []byte("3")})
}
// Ensure that a leaf can deserialize from a page.
func TestLeafRead(t *testing.T) {
// Create a page.
var buf [4096]byte
page := (*page)(unsafe.Pointer(&buf[0]))
page.count = 2
// Insert 2 leaf items at the beginning. sizeof(lnode) == 16
nodes := (*[3]lnode)(unsafe.Pointer(&page.ptr))
nodes[0] = lnode{flags: 0, pos: 32, ksize: 3, vsize: 4} // pos = sizeof(lnode) * 2
nodes[1] = lnode{flags: 0, pos: 23, ksize: 10, vsize: 3} // pos = sizeof(lnode) + 3 + 4
// Write data for the nodes at the end.
data := (*[4096]byte)(unsafe.Pointer(&nodes[2]))
copy(data[:], []byte("barfooz"))
copy(data[7:], []byte("helloworldbye"))
// Deserialize page into a leaf.
l := &leaf{}
l.read(page)
// Check that there are two items with correct data.
assert.Equal(t, len(l.items), 2)
assert.Equal(t, l.items[0].key, []byte("bar"))
assert.Equal(t, l.items[0].value, []byte("fooz"))
assert.Equal(t, l.items[1].key, []byte("helloworld"))
assert.Equal(t, l.items[1].value, []byte("bye"))
}
// Ensure that a leaf can serialize itself.
func TestLeafWrite(t *testing.T) {
// Create a leaf.
l := &leaf{items: make(leafItems, 0)}
l.put([]byte("susy"), []byte("que"))
l.put([]byte("ricki"), []byte("lake"))
l.put([]byte("john"), []byte("johnson"))
// Write it to a page.
var buf [4096]byte
p := (*page)(unsafe.Pointer(&buf[0]))
l.write(p)
// Read the page back in.
l2 := &leaf{}
l2.read(p)
// Check that the two pages are the same.
assert.Equal(t, len(l2.items), 3)
assert.Equal(t, l2.items[0].key, []byte("john"))
assert.Equal(t, l2.items[0].value, []byte("johnson"))
assert.Equal(t, l2.items[1].key, []byte("ricki"))
assert.Equal(t, l2.items[1].value, []byte("lake"))
assert.Equal(t, l2.items[2].key, []byte("susy"))
assert.Equal(t, l2.items[2].value, []byte("que"))
}
// Ensure that a leaf can split into appropriate subgroups.
func TestLeafSplit(t *testing.T) {
// Create a leaf.
l := &leaf{items: make(leafItems, 0)}
l.put([]byte("00000001"), []byte("0123456701234567"))
l.put([]byte("00000002"), []byte("0123456701234567"))
l.put([]byte("00000003"), []byte("0123456701234567"))
l.put([]byte("00000004"), []byte("0123456701234567"))
l.put([]byte("00000005"), []byte("0123456701234567"))
// Split between 3 & 4.
leafs := l.split(100)
assert.Equal(t, len(leafs), 2)
assert.Equal(t, len(leafs[0].items), 2)
assert.Equal(t, len(leafs[1].items), 3)
}
// Ensure that a leaf with the minimum number of items just returns a single leaf.
func TestLeafSplitWithMinKeys(t *testing.T) {
// Create a leaf.
l := &leaf{items: make(leafItems, 0)}
l.put([]byte("00000001"), []byte("0123456701234567"))
l.put([]byte("00000002"), []byte("0123456701234567"))
// Split.
leafs := l.split(20)
assert.Equal(t, len(leafs), 1)
assert.Equal(t, len(leafs[0].items), 2)
}
// Ensure that a leaf that has keys that all fit on a page just returns one leaf.
func TestLeafSplitFitsInPage(t *testing.T) {
// Create a leaf.
l := &leaf{items: make(leafItems, 0)}
l.put([]byte("00000001"), []byte("0123456701234567"))
l.put([]byte("00000002"), []byte("0123456701234567"))
l.put([]byte("00000003"), []byte("0123456701234567"))
l.put([]byte("00000004"), []byte("0123456701234567"))
l.put([]byte("00000005"), []byte("0123456701234567"))
// Split.
leafs := l.split(4096)
assert.Equal(t, len(leafs), 1)
assert.Equal(t, len(leafs[0].items), 5)
}