Files
srdb/btree/btree_test.go
bourdon ae87c38776 Initial commit: SRDB - High-performance LSM-Tree database
- Core engine with MemTable, SST, WAL
- B+Tree indexing for SST files  
- Leveled compaction strategy
- Multi-table database management
- Schema validation and secondary indexes
- Query builder with complex conditions
- Web UI with HTMX for data visualization
- Command-line tools for diagnostics
2025-10-08 06:38:28 +08:00

156 lines
3.2 KiB
Go

package btree
import (
"os"
"testing"
"github.com/edsrzf/mmap-go"
)
func TestBTree(t *testing.T) {
// 1. 创建测试文件
file, err := os.Create("test.sst")
if err != nil {
t.Fatal(err)
}
defer os.Remove("test.sst")
// 2. 构建 B+Tree
builder := NewBuilder(file, 256) // 从 offset 256 开始
// 添加 1000 个 key-value
for i := int64(1); i <= 1000; i++ {
dataOffset := 1000000 + i*100 // 模拟数据位置
dataSize := int32(100)
err := builder.Add(i, dataOffset, dataSize)
if err != nil {
t.Fatal(err)
}
}
// 构建
rootOffset, err := builder.Build()
if err != nil {
t.Fatal(err)
}
t.Logf("Root offset: %d", rootOffset)
// 3. 关闭并重新打开文件
file.Close()
file, err = os.Open("test.sst")
if err != nil {
t.Fatal(err)
}
defer file.Close()
// 4. mmap 映射
mmapData, err := mmap.Map(file, mmap.RDONLY, 0)
if err != nil {
t.Fatal(err)
}
defer mmapData.Unmap()
// 5. 查询测试
reader := NewReader(mmapData, rootOffset)
// 测试存在的 key
for i := int64(1); i <= 1000; i++ {
offset, size, found := reader.Get(i)
if !found {
t.Errorf("Key %d not found", i)
}
expectedOffset := 1000000 + i*100
if offset != expectedOffset {
t.Errorf("Key %d: expected offset %d, got %d", i, expectedOffset, offset)
}
if size != 100 {
t.Errorf("Key %d: expected size 100, got %d", i, size)
}
}
// 测试不存在的 key
_, _, found := reader.Get(1001)
if found {
t.Error("Key 1001 should not exist")
}
_, _, found = reader.Get(0)
if found {
t.Error("Key 0 should not exist")
}
t.Log("All tests passed!")
}
func TestBTreeSerialization(t *testing.T) {
// 测试节点序列化
leaf := NewLeafNode()
leaf.AddData(1, 1000, 100)
leaf.AddData(2, 2000, 200)
leaf.AddData(3, 3000, 300)
// 序列化
data := leaf.Marshal()
if len(data) != NodeSize {
t.Errorf("Expected size %d, got %d", NodeSize, len(data))
}
// 反序列化
leaf2 := Unmarshal(data)
if leaf2 == nil {
t.Fatal("Unmarshal failed")
}
// 验证
if leaf2.NodeType != NodeTypeLeaf {
t.Error("Wrong node type")
}
if leaf2.KeyCount != 3 {
t.Errorf("Expected 3 keys, got %d", leaf2.KeyCount)
}
if len(leaf2.Keys) != 3 {
t.Errorf("Expected 3 keys, got %d", len(leaf2.Keys))
}
if leaf2.Keys[0] != 1 || leaf2.Keys[1] != 2 || leaf2.Keys[2] != 3 {
t.Error("Keys mismatch")
}
if leaf2.DataOffsets[0] != 1000 || leaf2.DataOffsets[1] != 2000 || leaf2.DataOffsets[2] != 3000 {
t.Error("Data offsets mismatch")
}
if leaf2.DataSizes[0] != 100 || leaf2.DataSizes[1] != 200 || leaf2.DataSizes[2] != 300 {
t.Error("Data sizes mismatch")
}
t.Log("Serialization test passed!")
}
func BenchmarkBTreeGet(b *testing.B) {
// 构建测试数据
file, _ := os.Create("bench.sst")
defer os.Remove("bench.sst")
builder := NewBuilder(file, 256)
for i := int64(1); i <= 100000; i++ {
builder.Add(i, i*100, 100)
}
rootOffset, _ := builder.Build()
file.Close()
// mmap
file, _ = os.Open("bench.sst")
defer file.Close()
mmapData, _ := mmap.Map(file, mmap.RDONLY, 0)
defer mmapData.Unmap()
reader := NewReader(mmapData, rootOffset)
// 性能测试
b.ResetTimer()
for i := 0; i < b.N; i++ {
key := int64(i%100000 + 1)
reader.Get(key)
}
}