diff --git a/merklebtree/btree.go b/merklebtree/btree.go new file mode 100644 index 0000000..67a7a96 --- /dev/null +++ b/merklebtree/btree.go @@ -0,0 +1,634 @@ +// Copyright (c) 2015, Emir Pasic. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package btree implements a B tree. +// +// According to Knuth's definition, a B-tree of order m is a tree which satisfies the following properties: +// - Every node has at most m children. +// - Every non-leaf node (except root) has at least ⌈m/2⌉ children. +// - The root has at least two children if it is not a leaf node. +// - A non-leaf node with k children contains k−1 keys. +// - All leaves appear in the same level +// +// Structure is not thread safe. +// +// References: https://en.wikipedia.org/wiki/B-tree +package merklebtree + +import ( + "crypto/sha256" + "encoding/hex" +) + +// Tree holds elements of the B-tree +type Tree struct { + Root *Node // Root node + size int // Total number of keys in the tree + m int // order (maximum number of children) +} + +// Node is a single element within the tree +type Node struct { + Parent *Node + Hash []byte + Contents []*Content // Contained keys in node + Children []*Node // Children nodes +} + +func (node *Node) Put(item Content) { + node.Contents = append(node.Contents, &item) +} + +// CalculateHash update the merkle hash of node,include children and content. +func (tree *Tree) CalculateHash(node *Node) ([]byte, error) { + h := sha256.New() + var bytes []byte + + for _, content := range node.Contents { + hash, err := (*content).CalculateHash() + if err != nil { + return nil, err + } + bytes = append(bytes, hash...) + } + + for _, children := range node.Children { + bytes = append(bytes, children.Hash...) + } + + if _, err := h.Write(bytes); err != nil { + return nil, err + } + + node.Hash = h.Sum(nil) + + return node.Hash, nil +} + +//ReCalculateMerkleRoot update Merkleroot from node to root node. +func (tree *Tree) ReCalculateMerkleRoot(node *Node) ([]byte, error) { + if node == tree.Root { + return tree.CalculateHash(node) + } else { + _, err := tree.CalculateHash(node) + if err != nil { + return nil, err + } + return tree.ReCalculateMerkleRoot(node.Parent) + } +} + +type Content interface { + // CalculateHash calculate the hash of content + CalculateHash() ([]byte, error) + + // If a.Comparator(b) return + // negative , if a < b + // zero , if a == b + // positive , if a > b + Comparator(than Content) int +} + +// NewWith instantiates a B-tree with the order (maximum number of children) and a custom key comparator. +func NewWith(order int) *Tree { + if order < 3 { + panic("Invalid order, should be at least 3") + } + return &Tree{m: order} +} + +// Put inserts key-value pair node into the tree. +// If key already exists, then its value is updated with the new value. +// Key should adhere to the comparator's type assertion, otherwise method panics. +func (tree *Tree) Put(item Content) { + content := &item + + if tree.Root == nil { + tree.Root = &Node{Contents: []*Content{content}, Children: []*Node{}} + tree.size++ + + //calculate merkle root hash + _, err := tree.ReCalculateMerkleRoot(tree.Root) + if err != nil { + panic(err) + } + + return + } + + if tree.insert(tree.Root, content) { + tree.size++ + } +} + +// Get searches the node in the tree by key and returns its value or nil if key is not found in tree. +// Second return parameter is true if key was found, otherwise false. +// Key should adhere to the comparator's type assertion, otherwise method panics. +func (tree *Tree) Get(item Content) (result Content, found bool) { + node, index, found := tree.searchRecursively(tree.Root, item) + if found { + return *node.Contents[index], true + } + return item, false +} + +// Remove remove the node from the tree by key. +// Key should adhere to the comparator's type assertion, otherwise method panics. +func (tree *Tree) Remove(item Content) { + node, index, found := tree.searchRecursively(tree.Root, item) + if found { + tree.delete(node, index) + tree.size-- + } +} + +// Empty returns true if tree does not contain any nodes +func (tree *Tree) Empty() bool { + return tree.size == 0 +} + +// Size returns number of nodes in the tree. +func (tree *Tree) Size() int { + return tree.size +} + +// Keys returns all keys in-order +func (tree *Tree) Contents() []Content { + contents := make([]Content, tree.size) + it := tree.Iterator() + for i := 0; it.Next(); i++ { + contents[i] = it.Item() + } + return contents +} + +// Clear removes all nodes from the tree. +func (tree *Tree) Clear() { + tree.Root = nil + tree.size = 0 +} + +func (tree *Tree) MerkleBTreeRoot() string { + if tree.Root == nil { + return "" + } else { + return hex.EncodeToString(tree.Root.Hash) + } +} + +// Height returns the height of the tree. +func (tree *Tree) Height() int { + return tree.Root.height() +} + +// Left returns the left-most (min) node or nil if tree is empty. +func (tree *Tree) Left() *Node { + return tree.left(tree.Root) +} + +// LeftKey returns the left-most (min) key or nil if tree is empty. +func (tree *Tree) LeftItem() Content { + if left := tree.Left(); left != nil { + return *left.Contents[0] + } + return nil +} + +// Right returns the right-most (max) node or nil if tree is empty. +func (tree *Tree) Right() *Node { + return tree.right(tree.Root) +} + +// RightKey returns the right-most (max) key or nil if tree is empty. +func (tree *Tree) RightItem() Content { + if right := tree.Right(); right != nil { + return *right.Contents[len(right.Contents)-1] + } + return nil +} + +func (node *Node) height() int { + height := 0 + for ; node != nil; node = node.Children[0] { + height++ + if len(node.Children) == 0 { + break + } + } + return height +} + +func (tree *Tree) isLeaf(node *Node) bool { + return len(node.Children) == 0 +} + +func (tree *Tree) isFull(node *Node) bool { + return len(node.Contents) == tree.maxContents() +} + +func (tree *Tree) shouldSplit(node *Node) bool { + return len(node.Contents) > tree.maxContents() +} + +func (tree *Tree) maxChildren() int { + return tree.m +} + +func (tree *Tree) minChildren() int { + return (tree.m + 1) / 2 // ceil(m/2) +} + +func (tree *Tree) maxContents() int { + return tree.maxChildren() - 1 +} + +func (tree *Tree) minContents() int { + return tree.minChildren() - 1 +} + +func (tree *Tree) middle() int { + return (tree.m - 1) / 2 // "-1" to favor right nodes to have more keys when splitting +} + +// search searches only within the single node among its contents +func (tree *Tree) search(node *Node, item Content) (index int, found bool) { + low, high := 0, len(node.Contents)-1 + var mid int + for low <= high { + mid = (high + low) / 2 + compare := item.Comparator(*node.Contents[mid]) + switch { + case compare > 0: + low = mid + 1 + case compare < 0: + high = mid - 1 + case compare == 0: + return mid, true + } + } + return low, false +} + +// level traversal the tree and return the node +func (tree *Tree) levelTraversal() [][]*Node { + var nodes [][]*Node + if tree.Root == nil { + return nodes + } + var startnodes, nextnodes []*Node + startnodes = append(startnodes, tree.Root) + nodes = append(nodes, startnodes) + + for true { + for _, node := range startnodes { + nextnodes = append(nextnodes, node.Children...) + } + nodes = append(nodes, nextnodes) + startnodes = nextnodes + nextnodes = nil + if len(startnodes) == 0 { + break + } + if tree.isLeaf(startnodes[0]) { + break + } + } + + return nodes +} + +// calculate the MerkleRoot of tree +func (tree *Tree) calculateMerkleRoot() string { + if tree.Root == nil { + return "" + } + nodes := tree.levelTraversal() + for i := len(nodes) - 1; i > 0; i-- { + for j := 0; j < len(nodes[i]); j++ { + //reset nodes[i][j] Hash + nodes[i][j].Hash = nil + tree.CalculateHash(nodes[i][j]) + } + } + return hex.EncodeToString(nodes[0][0].Hash) +} + +// searchRecursively searches recursively down the tree starting at the startNode +func (tree *Tree) searchRecursively(startNode *Node, item Content) (node *Node, index int, found bool) { + if tree.Empty() { + return nil, -1, false + } + node = startNode + for { + index, found = tree.search(node, item) + if found { + return node, index, true + } + if tree.isLeaf(node) { + return nil, -1, false + } + node = node.Children[index] + } +} + +func (tree *Tree) insert(node *Node, content *Content) (inserted bool) { + if tree.isLeaf(node) { + return tree.insertIntoLeaf(node, content) + } + return tree.insertIntoInternal(node, content) +} + +func (tree *Tree) insertIntoLeaf(node *Node, content *Content) (inserted bool) { + insertPosition, found := tree.search(node, *content) + if found { + node.Contents[insertPosition] = content + tree.ReCalculateMerkleRoot(node) + return false + } + // Insert content's key in the middle of the node + node.Contents = append(node.Contents, nil) + copy(node.Contents[insertPosition+1:], node.Contents[insertPosition:]) + node.Contents[insertPosition] = content + tree.split(node) + return true +} + +func (tree *Tree) insertIntoInternal(node *Node, content *Content) (inserted bool) { + insertPosition, found := tree.search(node, *content) + if found { + node.Contents[insertPosition] = content + tree.ReCalculateMerkleRoot(node) + return false + } + return tree.insert(node.Children[insertPosition], content) +} + +func (tree *Tree) split(node *Node) { + if !tree.shouldSplit(node) { + tree.ReCalculateMerkleRoot(node) + return + } + + if node == tree.Root { + tree.splitRoot() + return + } + + tree.splitNonRoot(node) +} + +func (tree *Tree) splitNonRoot(node *Node) { + middle := tree.middle() + parent := node.Parent + + left := &Node{Contents: append([]*Content(nil), node.Contents[:middle]...), Parent: parent} + right := &Node{Contents: append([]*Content(nil), node.Contents[middle+1:]...), Parent: parent} + + // Move children from the node to be split into left and right nodes + if !tree.isLeaf(node) { + left.Children = append([]*Node(nil), node.Children[:middle+1]...) + right.Children = append([]*Node(nil), node.Children[middle+1:]...) + setParent(left.Children, left) + setParent(right.Children, right) + } + + insertPosition, _ := tree.search(parent, *node.Contents[middle]) + + // Insert middle key into parent + parent.Contents = append(parent.Contents, nil) + copy(parent.Contents[insertPosition+1:], parent.Contents[insertPosition:]) + parent.Contents[insertPosition] = node.Contents[middle] + + // Set child left of inserted key in parent to the created left node + parent.Children[insertPosition] = left + + // Set child right of inserted key in parent to the created right node + parent.Children = append(parent.Children, nil) + copy(parent.Children[insertPosition+2:], parent.Children[insertPosition+1:]) + parent.Children[insertPosition+1] = right + + tree.CalculateHash(left) + tree.CalculateHash(right) + tree.CalculateHash(parent) + + tree.split(parent) +} + +func (tree *Tree) splitRoot() { + middle := tree.middle() + + left := &Node{Contents: append([]*Content(nil), tree.Root.Contents[:middle]...)} + right := &Node{Contents: append([]*Content(nil), tree.Root.Contents[middle+1:]...)} + + // Move children from the node to be split into left and right nodes + if !tree.isLeaf(tree.Root) { + left.Children = append([]*Node(nil), tree.Root.Children[:middle+1]...) + right.Children = append([]*Node(nil), tree.Root.Children[middle+1:]...) + setParent(left.Children, left) + setParent(right.Children, right) + } + tree.CalculateHash(left) + tree.CalculateHash(right) + + // Root is a node with one content and two children (left and right) + newRoot := &Node{ + Contents: []*Content{tree.Root.Contents[middle]}, + Children: []*Node{left, right}, + } + + left.Parent = newRoot + right.Parent = newRoot + tree.Root = newRoot + tree.CalculateHash(newRoot) +} + +func setParent(nodes []*Node, parent *Node) { + for _, node := range nodes { + node.Parent = parent + } +} + +func (tree *Tree) left(node *Node) *Node { + if tree.Empty() { + return nil + } + current := node + for { + if tree.isLeaf(current) { + return current + } + current = current.Children[0] + } +} + +func (tree *Tree) right(node *Node) *Node { + if tree.Empty() { + return nil + } + current := node + for { + if tree.isLeaf(current) { + return current + } + current = current.Children[len(current.Children)-1] + } +} + +// leftSibling returns the node's left sibling and child index (in parent) if it exists, otherwise (nil,-1) +// key is any of keys in node (could even be deleted). +func (tree *Tree) leftSibling(node *Node, item Content) (*Node, int) { + if node.Parent != nil { + index, _ := tree.search(node.Parent, item) + index-- + if index >= 0 && index < len(node.Parent.Children) { + return node.Parent.Children[index], index + } + } + return nil, -1 +} + +// rightSibling returns the node's right sibling and child index (in parent) if it exists, otherwise (nil,-1) +// key is any of keys in node (could even be deleted). +func (tree *Tree) rightSibling(node *Node, item Content) (*Node, int) { + if node.Parent != nil { + index, _ := tree.search(node.Parent, item) + index++ + if index < len(node.Parent.Children) { + return node.Parent.Children[index], index + } + } + return nil, -1 +} + +// delete deletes an content in node at contents' index +// ref.: https://en.wikipedia.org/wiki/B-tree#Deletion +func (tree *Tree) delete(node *Node, index int) { + // deleting from a leaf node + if tree.isLeaf(node) { + deletedKey := node.Contents[index] + tree.deleteContent(node, index) + tree.rebalance(node, *deletedKey) + if len(tree.Root.Contents) == 0 { + tree.Root = nil + } + return + } + + // deleting from an internal node + leftLargestNode := tree.right(node.Children[index]) // largest node in the left sub-tree (assumed to exist) + leftLargestContentIndex := len(leftLargestNode.Contents) - 1 + node.Contents[index] = leftLargestNode.Contents[leftLargestContentIndex] + deletedKey := leftLargestNode.Contents[leftLargestContentIndex] + tree.deleteContent(leftLargestNode, leftLargestContentIndex) + tree.rebalance(leftLargestNode, *deletedKey) +} + +// rebalance rebalances the tree after deletion if necessary and returns true, otherwise false. +// Note that we first delete the content and then call rebalance, thus the passed deleted key as reference. +func (tree *Tree) rebalance(node *Node, deletedItem Content) { + // check if rebalancing is needed + if node == nil || len(node.Contents) >= tree.minContents() { + //recalculate merkle root from leaf node + if node != nil { + //root is not nil + tree.ReCalculateMerkleRoot(node) + } + return + } + + // try to borrow from left sibling + leftSibling, leftSiblingIndex := tree.leftSibling(node, deletedItem) + if leftSibling != nil && len(leftSibling.Contents) > tree.minContents() { + // rotate right + node.Contents = append([]*Content{node.Parent.Contents[leftSiblingIndex]}, node.Contents...) // prepend parent's separator content to node's contents + node.Parent.Contents[leftSiblingIndex] = leftSibling.Contents[len(leftSibling.Contents)-1] + tree.deleteContent(leftSibling, len(leftSibling.Contents)-1) + if !tree.isLeaf(leftSibling) { + leftSiblingRightMostChild := leftSibling.Children[len(leftSibling.Children)-1] + leftSiblingRightMostChild.Parent = node + node.Children = append([]*Node{leftSiblingRightMostChild}, node.Children...) + tree.deleteChild(leftSibling, len(leftSibling.Children)-1) + } + tree.CalculateHash(node) + tree.CalculateHash(leftSibling) + return + } + + // try to borrow from right sibling + rightSibling, rightSiblingIndex := tree.rightSibling(node, deletedItem) + if rightSibling != nil && len(rightSibling.Contents) > tree.minContents() { + // rotate left + node.Contents = append(node.Contents, node.Parent.Contents[rightSiblingIndex-1]) // append parent's separator content to node's contents + node.Parent.Contents[rightSiblingIndex-1] = rightSibling.Contents[0] + tree.deleteContent(rightSibling, 0) + if !tree.isLeaf(rightSibling) { + rightSiblingLeftMostChild := rightSibling.Children[0] + rightSiblingLeftMostChild.Parent = node + node.Children = append(node.Children, rightSiblingLeftMostChild) + tree.deleteChild(rightSibling, 0) + } + tree.CalculateHash(node) + tree.CalculateHash(rightSibling) + return + } + + // merge with siblings + if rightSibling != nil { + // merge with right sibling + node.Contents = append(node.Contents, node.Parent.Contents[rightSiblingIndex-1]) + node.Contents = append(node.Contents, rightSibling.Contents...) + deletedItem = *node.Parent.Contents[rightSiblingIndex-1] + tree.deleteContent(node.Parent, rightSiblingIndex-1) + tree.appendChildren(node.Parent.Children[rightSiblingIndex], node) + tree.deleteChild(node.Parent, rightSiblingIndex) + tree.CalculateHash(node) + } else if leftSibling != nil { + // merge with left sibling + contents := append([]*Content(nil), leftSibling.Contents...) + contents = append(contents, node.Parent.Contents[leftSiblingIndex]) + node.Contents = append(contents, node.Contents...) + deletedItem = *node.Parent.Contents[leftSiblingIndex] + tree.deleteContent(node.Parent, leftSiblingIndex) + tree.prependChildren(node.Parent.Children[leftSiblingIndex], node) + tree.deleteChild(node.Parent, leftSiblingIndex) + tree.CalculateHash(node) + } + + // make the merged node the root if its parent was the root and the root is empty + if node.Parent == tree.Root && len(tree.Root.Contents) == 0 { + tree.Root = node + node.Parent = nil + tree.CalculateHash(tree.Root) + return + } + + // parent might underflow, so try to rebalance if necessary + tree.rebalance(node.Parent, deletedItem) +} + +func (tree *Tree) prependChildren(fromNode *Node, toNode *Node) { + children := append([]*Node(nil), fromNode.Children...) + toNode.Children = append(children, toNode.Children...) + setParent(fromNode.Children, toNode) +} + +func (tree *Tree) appendChildren(fromNode *Node, toNode *Node) { + toNode.Children = append(toNode.Children, fromNode.Children...) + setParent(fromNode.Children, toNode) +} + +func (tree *Tree) deleteContent(node *Node, index int) { + copy(node.Contents[index:], node.Contents[index+1:]) + node.Contents[len(node.Contents)-1] = nil + node.Contents = node.Contents[:len(node.Contents)-1] +} + +func (tree *Tree) deleteChild(node *Node, index int) { + if index >= len(node.Children) { + return + } + copy(node.Children[index:], node.Children[index+1:]) + node.Children[len(node.Children)-1] = nil + node.Children = node.Children[:len(node.Children)-1] +} diff --git a/merklebtree/btree_test.go b/merklebtree/btree_test.go new file mode 100644 index 0000000..4feddd2 --- /dev/null +++ b/merklebtree/btree_test.go @@ -0,0 +1,1380 @@ +// Copyright (c) 2015, Emir Pasic. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package merklebtree + +import ( + "crypto/sha256" + "encoding/json" + "fmt" + "testing" +) + +// Int implements the Item interface for integers. +type Item struct { + Key int `json:"key"` + Value string `json:"value"` +} + +type Item2 struct { + Key int `json:"key"` + Value int `json:"value"` +} + +type Item3 struct { + Key int `json:"key"` + Value interface{} `json:"value"` +} + +type TestData struct { + Item + result bool +} + +// IntComparator provides a basic comparison on int +func (a Item) Comparator(b Content) int { + bAsserted := b.(Item) + switch { + case a.Key > bAsserted.Key: + return 1 + case a.Key < bAsserted.Key: + return -1 + default: + return 0 + } +} + +func (a Item) CalculateHash() ([]byte, error) { + h := sha256.New() + jsonBytes, err := json.Marshal(a) + if err != nil { + return nil, err + } + if _, err := h.Write(jsonBytes); err != nil { + return nil, err + } + + return h.Sum(nil), nil +} + +// IntComparator provides a basic comparison on int +func (a Item2) Comparator(b Content) int { + bAsserted := b.(Item2) + switch { + case a.Key > bAsserted.Key: + return 1 + case a.Key < bAsserted.Key: + return -1 + default: + return 0 + } +} + +func (a Item2) CalculateHash() ([]byte, error) { + h := sha256.New() + jsonBytes, err := json.Marshal(a) + if err != nil { + return nil, err + } + if _, err := h.Write(jsonBytes); err != nil { + return nil, err + } + + return h.Sum(nil), nil +} + +// IntComparator provides a basic comparison on int +func (a Item3) Comparator(b Content) int { + bAsserted := b.(Item3) + switch { + case a.Key > bAsserted.Key: + return 1 + case a.Key < bAsserted.Key: + return -1 + default: + return 0 + } +} + +func (a Item3) CalculateHash() ([]byte, error) { + h := sha256.New() + jsonBytes, err := json.Marshal(a) + if err != nil { + return nil, err + } + if _, err := h.Write(jsonBytes); err != nil { + return nil, err + } + + return h.Sum(nil), nil +} + +func TestBTreeGet1(t *testing.T) { + tree := NewWith(3) + tree.Put(Item{Key: 1, Value: "a"}) + tree.Put(Item{Key: 2, Value: "b"}) + tree.Put(Item{Key: 3, Value: "c"}) + tree.Put(Item{Key: 4, Value: "d"}) + tree.Put(Item{Key: 5, Value: "e"}) + tree.Put(Item{Key: 6, Value: "f"}) + tree.Put(Item{Key: 7, Value: "g"}) + + tests := [][]interface{}{ + {0, "", false}, + {1, "a", true}, + {2, "b", true}, + {3, "c", true}, + {4, "d", true}, + {5, "e", true}, + {6, "f", true}, + {7, "g", true}, + {8, "", false}, + } + // + for _, test := range tests { + item, found := tree.Get(Item{Key: test[0].(int), Value: test[1].(string)}) + if item.(Item).Value != test[1] || found != test[2] { + t.Errorf("Got %v,%v expected %v,%v", item.(Item).Value, found, test[1], test[2]) + } + } +} + +// +func TestBTreeGet2(t *testing.T) { + tree := NewWith(3) + tree.Put(Item{Key: 7, Value: "g"}) + tree.Put(Item{Key: 9, Value: "i"}) + tree.Put(Item{Key: 10, Value: "j"}) + tree.Put(Item{Key: 6, Value: "f"}) + tree.Put(Item{Key: 3, Value: "c"}) + tree.Put(Item{Key: 4, Value: "d"}) + tree.Put(Item{Key: 5, Value: "e"}) + tree.Put(Item{Key: 8, Value: "h"}) + tree.Put(Item{Key: 2, Value: "b"}) + tree.Put(Item{Key: 1, Value: "a"}) + + tests := [][]interface{}{ + {0, "", false}, + {1, "a", true}, + {2, "b", true}, + {3, "c", true}, + {4, "d", true}, + {5, "e", true}, + {6, "f", true}, + {7, "g", true}, + {8, "h", true}, + {9, "i", true}, + {10, "j", true}, + {11, "", false}, + } + + for _, test := range tests { + if Value, found := tree.Get(Item{Key: test[0].(int), Value: test[1].(string)}); Value.(Item).Value != test[1] || found != test[2] { + t.Errorf("Got %v,%v expected %v,%v", Value, found, test[1], test[2]) + } + } +} + +// +func TestBTreePut1(t *testing.T) { + // https://upload.wikimedia.org/wikipedia/commons/3/33/B_tree_insertion_example.png + tree := NewWith(3) + assertValidTree(t, tree, 0) + + tree.Put(Item2{Key: 1, Value: 0}) + assertValidTree(t, tree, 1) + assertValidTreeNode(t, tree.Root, 1, 0, []int{1}, false) + + tree.Put(Item2{Key: 2, Value: 1}) + assertValidTree(t, tree, 2) + assertValidTreeNode(t, tree.Root, 2, 0, []int{1, 2}, false) + + tree.Put(Item2{Key: 3, Value: 2}) + assertValidTree(t, tree, 3) + assertValidTreeNode(t, tree.Root, 1, 2, []int{2}, false) + assertValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{1}, true) + assertValidTreeNode(t, tree.Root.Children[1], 1, 0, []int{3}, true) + + tree.Put(Item2{Key: 4, Value: 2}) + assertValidTree(t, tree, 4) + assertValidTreeNode(t, tree.Root, 1, 2, []int{2}, false) + assertValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{1}, true) + assertValidTreeNode(t, tree.Root.Children[1], 2, 0, []int{3, 4}, true) + // + tree.Put(Item2{Key: 5, Value: 2}) + assertValidTree(t, tree, 5) + assertValidTreeNode(t, tree.Root, 2, 3, []int{2, 4}, false) + assertValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{1}, true) + assertValidTreeNode(t, tree.Root.Children[1], 1, 0, []int{3}, true) + assertValidTreeNode(t, tree.Root.Children[2], 1, 0, []int{5}, true) + + tree.Put(Item2{Key: 6, Value: 2}) + assertValidTree(t, tree, 6) + assertValidTreeNode(t, tree.Root, 2, 3, []int{2, 4}, false) + assertValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{1}, true) + assertValidTreeNode(t, tree.Root.Children[1], 1, 0, []int{3}, true) + assertValidTreeNode(t, tree.Root.Children[2], 2, 0, []int{5, 6}, true) + + tree.Put(Item2{Key: 7, Value: 2}) + assertValidTree(t, tree, 7) + assertValidTreeNode(t, tree.Root, 1, 2, []int{4}, false) + assertValidTreeNode(t, tree.Root.Children[0], 1, 2, []int{2}, true) + assertValidTreeNode(t, tree.Root.Children[1], 1, 2, []int{6}, true) + assertValidTreeNode(t, tree.Root.Children[0].Children[0], 1, 0, []int{1}, true) + assertValidTreeNode(t, tree.Root.Children[0].Children[1], 1, 0, []int{3}, true) + assertValidTreeNode(t, tree.Root.Children[1].Children[0], 1, 0, []int{5}, true) + assertValidTreeNode(t, tree.Root.Children[1].Children[1], 1, 0, []int{7}, true) +} + +func TestBTreePut2(t *testing.T) { + tree := NewWith(4) + assertValidTree(t, tree, 0) + + tree.Put(Item2{Key: 0, Value: 0}) + assertValidTree(t, tree, 1) + assertValidTreeNode(t, tree.Root, 1, 0, []int{0}, false) + + tree.Put(Item2{Key: 2, Value: 2}) + assertValidTree(t, tree, 2) + assertValidTreeNode(t, tree.Root, 2, 0, []int{0, 2}, false) + + tree.Put(Item2{Key: 1, Value: 1}) + assertValidTree(t, tree, 3) + assertValidTreeNode(t, tree.Root, 3, 0, []int{0, 1, 2}, false) + + tree.Put(Item2{Key: 1, Value: 1}) + assertValidTree(t, tree, 3) + assertValidTreeNode(t, tree.Root, 3, 0, []int{0, 1, 2}, false) + + tree.Put(Item2{Key: 3, Value: 3}) + assertValidTree(t, tree, 4) + assertValidTreeNode(t, tree.Root, 1, 2, []int{1}, false) + assertValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{0}, true) + assertValidTreeNode(t, tree.Root.Children[1], 2, 0, []int{2, 3}, true) + + tree.Put(Item2{Key: 4, Value: 4}) + assertValidTree(t, tree, 5) + assertValidTreeNode(t, tree.Root, 1, 2, []int{1}, false) + assertValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{0}, true) + assertValidTreeNode(t, tree.Root.Children[1], 3, 0, []int{2, 3, 4}, true) + + tree.Put(Item2{Key: 5, Value: 5}) + assertValidTree(t, tree, 6) + assertValidTreeNode(t, tree.Root, 2, 3, []int{1, 3}, false) + assertValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{0}, true) + assertValidTreeNode(t, tree.Root.Children[1], 1, 0, []int{2}, true) + assertValidTreeNode(t, tree.Root.Children[2], 2, 0, []int{4, 5}, true) +} + +// +func TestBTreePut3(t *testing.T) { + // http://www.geeksforgeeks.org/b-tree-set-1-insert-2/ + tree := NewWith(6) + assertValidTree(t, tree, 0) + + tree.Put(Item2{Key: 10, Value: 0}) + assertValidTree(t, tree, 1) + assertValidTreeNode(t, tree.Root, 1, 0, []int{10}, false) + + tree.Put(Item2{Key: 20, Value: 1}) + assertValidTree(t, tree, 2) + assertValidTreeNode(t, tree.Root, 2, 0, []int{10, 20}, false) + + tree.Put(Item2{Key: 30, Value: 2}) + assertValidTree(t, tree, 3) + assertValidTreeNode(t, tree.Root, 3, 0, []int{10, 20, 30}, false) + + tree.Put(Item2{Key: 40, Value: 3}) + assertValidTree(t, tree, 4) + assertValidTreeNode(t, tree.Root, 4, 0, []int{10, 20, 30, 40}, false) + + tree.Put(Item2{Key: 50, Value: 4}) + assertValidTree(t, tree, 5) + assertValidTreeNode(t, tree.Root, 5, 0, []int{10, 20, 30, 40, 50}, false) + + tree.Put(Item2{Key: 60, Value: 5}) + assertValidTree(t, tree, 6) + assertValidTreeNode(t, tree.Root, 1, 2, []int{30}, false) + assertValidTreeNode(t, tree.Root.Children[0], 2, 0, []int{10, 20}, true) + assertValidTreeNode(t, tree.Root.Children[1], 3, 0, []int{40, 50, 60}, true) + + tree.Put(Item2{Key: 70, Value: 6}) + assertValidTree(t, tree, 7) + assertValidTreeNode(t, tree.Root, 1, 2, []int{30}, false) + assertValidTreeNode(t, tree.Root.Children[0], 2, 0, []int{10, 20}, true) + assertValidTreeNode(t, tree.Root.Children[1], 4, 0, []int{40, 50, 60, 70}, true) + + tree.Put(Item2{Key: 80, Value: 7}) + assertValidTree(t, tree, 8) + assertValidTreeNode(t, tree.Root, 1, 2, []int{30}, false) + assertValidTreeNode(t, tree.Root.Children[0], 2, 0, []int{10, 20}, true) + assertValidTreeNode(t, tree.Root.Children[1], 5, 0, []int{40, 50, 60, 70, 80}, true) + + tree.Put(Item2{Key: 90, Value: 8}) + assertValidTree(t, tree, 9) + assertValidTreeNode(t, tree.Root, 2, 3, []int{30, 60}, false) + assertValidTreeNode(t, tree.Root.Children[0], 2, 0, []int{10, 20}, true) + assertValidTreeNode(t, tree.Root.Children[1], 2, 0, []int{40, 50}, true) + assertValidTreeNode(t, tree.Root.Children[2], 3, 0, []int{70, 80, 90}, true) +} + +// +func TestBTreePut4(t *testing.T) { + tree := NewWith(3) + assertValidTree(t, tree, 0) + + tree.Put(Item3{Key: 6, Value: nil}) + assertValidTree(t, tree, 1) + assertItem3ValidTreeNode(t, tree.Root, 1, 0, []int{6}, false) + + tree.Put(Item3{Key: 5, Value: nil}) + assertValidTree(t, tree, 2) + assertItem3ValidTreeNode(t, tree.Root, 2, 0, []int{5, 6}, false) + // + tree.Put(Item3{Key: 4, Value: nil}) + assertValidTree(t, tree, 3) + assertItem3ValidTreeNode(t, tree.Root, 1, 2, []int{5}, false) + assertItem3ValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{4}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1], 1, 0, []int{6}, true) + // + tree.Put(Item3{Key: 3, Value: nil}) + assertValidTree(t, tree, 4) + assertItem3ValidTreeNode(t, tree.Root, 1, 2, []int{5}, false) + assertItem3ValidTreeNode(t, tree.Root.Children[0], 2, 0, []int{3, 4}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1], 1, 0, []int{6}, true) + // + tree.Put(Item3{Key: 2, Value: nil}) + assertValidTree(t, tree, 5) + assertItem3ValidTreeNode(t, tree.Root, 2, 3, []int{3, 5}, false) + assertItem3ValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{2}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1], 1, 0, []int{4}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[2], 1, 0, []int{6}, true) + + tree.Put(Item3{Key: 1, Value: nil}) + assertValidTree(t, tree, 6) + assertItem3ValidTreeNode(t, tree.Root, 2, 3, []int{3, 5}, false) + assertItem3ValidTreeNode(t, tree.Root.Children[0], 2, 0, []int{1, 2}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1], 1, 0, []int{4}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[2], 1, 0, []int{6}, true) + + tree.Put(Item3{Key: 0, Value: nil}) + assertValidTree(t, tree, 7) + assertItem3ValidTreeNode(t, tree.Root, 1, 2, []int{3}, false) + assertItem3ValidTreeNode(t, tree.Root.Children[0], 1, 2, []int{1}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1], 1, 2, []int{5}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[0].Children[0], 1, 0, []int{0}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[0].Children[1], 1, 0, []int{2}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1].Children[0], 1, 0, []int{4}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1].Children[1], 1, 0, []int{6}, true) + + tree.Put(Item3{Key: -1, Value: nil}) + assertValidTree(t, tree, 8) + assertItem3ValidTreeNode(t, tree.Root, 1, 2, []int{3}, false) + assertItem3ValidTreeNode(t, tree.Root.Children[0], 1, 2, []int{1}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1], 1, 2, []int{5}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[0].Children[0], 2, 0, []int{-1, 0}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[0].Children[1], 1, 0, []int{2}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1].Children[0], 1, 0, []int{4}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1].Children[1], 1, 0, []int{6}, true) + + tree.Put(Item3{Key: -2, Value: nil}) + assertValidTree(t, tree, 9) + assertItem3ValidTreeNode(t, tree.Root, 1, 2, []int{3}, false) + assertItem3ValidTreeNode(t, tree.Root.Children[0], 2, 3, []int{-1, 1}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1], 1, 2, []int{5}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[0].Children[0], 1, 0, []int{-2}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[0].Children[1], 1, 0, []int{0}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[0].Children[2], 1, 0, []int{2}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1].Children[0], 1, 0, []int{4}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1].Children[1], 1, 0, []int{6}, true) + + tree.Put(Item3{Key: -3, Value: nil}) + assertValidTree(t, tree, 10) + assertItem3ValidTreeNode(t, tree.Root, 1, 2, []int{3}, false) + assertItem3ValidTreeNode(t, tree.Root.Children[0], 2, 3, []int{-1, 1}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1], 1, 2, []int{5}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[0].Children[0], 2, 0, []int{-3, -2}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[0].Children[1], 1, 0, []int{0}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[0].Children[2], 1, 0, []int{2}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1].Children[0], 1, 0, []int{4}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1].Children[1], 1, 0, []int{6}, true) + + tree.Put(Item3{Key: -4, Value: nil}) + assertValidTree(t, tree, 11) + assertItem3ValidTreeNode(t, tree.Root, 2, 3, []int{-1, 3}, false) + assertItem3ValidTreeNode(t, tree.Root.Children[0], 1, 2, []int{-3}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1], 1, 2, []int{1}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[2], 1, 2, []int{5}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[0].Children[0], 1, 0, []int{-4}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[0].Children[1], 1, 0, []int{-2}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1].Children[0], 1, 0, []int{0}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1].Children[1], 1, 0, []int{2}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[2].Children[0], 1, 0, []int{4}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[2].Children[1], 1, 0, []int{6}, true) +} + +// +func TestBTreeRemove1(t *testing.T) { + // empty + tree := NewWith(3) + tree.Remove(Item{Key: 1}) + assertValidTree(t, tree, 0) +} + +func TestBTreeRemove2(t *testing.T) { + // leaf node (no underflow) + tree := NewWith(3) + tree.Put(Item3{Key: 1, Value: nil}) + tree.Put(Item3{Key: 2, Value: nil}) + + tree.Remove(Item3{Key: 1}) + assertValidTree(t, tree, 1) + assertItem3ValidTreeNode(t, tree.Root, 1, 0, []int{2}, false) + + tree.Remove(Item3{Key: 2}) + assertValidTree(t, tree, 0) +} + +func TestBTreeRemove3(t *testing.T) { + // merge with right (underflow) + { + tree := NewWith(3) + tree.Put(Item3{Key: 1, Value: nil}) + tree.Put(Item3{Key: 2, Value: nil}) + tree.Put(Item3{Key: 3, Value: nil}) + + tree.Remove(Item3{Key: 1}) + assertValidTree(t, tree, 2) + assertItem3ValidTreeNode(t, tree.Root, 2, 0, []int{2, 3}, false) + } + // merge with left (underflow) + { + tree := NewWith(3) + tree.Put(Item3{Key: 1, Value: nil}) + tree.Put(Item3{Key: 2, Value: nil}) + tree.Put(Item3{Key: 3, Value: nil}) + + tree.Remove(Item3{Key: 3}) + assertValidTree(t, tree, 2) + assertItem3ValidTreeNode(t, tree.Root, 2, 0, []int{1, 2}, false) + } +} + +func TestBTreeRemove4(t *testing.T) { + // rotate left (underflow) + tree := NewWith(3) + tree.Put(Item3{Key: 1, Value: nil}) + tree.Put(Item3{Key: 2, Value: nil}) + tree.Put(Item3{Key: 3, Value: nil}) + tree.Put(Item3{Key: 4, Value: nil}) + + assertValidTree(t, tree, 4) + assertItem3ValidTreeNode(t, tree.Root, 1, 2, []int{2}, false) + assertItem3ValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{1}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1], 2, 0, []int{3, 4}, true) + + tree.Remove(Item3{Key: 1}) + assertValidTree(t, tree, 3) + assertItem3ValidTreeNode(t, tree.Root, 1, 2, []int{3}, false) + assertItem3ValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{2}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1], 1, 0, []int{4}, true) +} + +func TestBTreeRemove5(t *testing.T) { + // rotate right (underflow) + tree := NewWith(3) + tree.Put(Item3{Key: 1, Value: nil}) + tree.Put(Item3{Key: 2, Value: nil}) + tree.Put(Item3{Key: 3, Value: nil}) + tree.Put(Item3{Key: 0, Value: nil}) + + assertValidTree(t, tree, 4) + assertItem3ValidTreeNode(t, tree.Root, 1, 2, []int{2}, false) + assertItem3ValidTreeNode(t, tree.Root.Children[0], 2, 0, []int{0, 1}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1], 1, 0, []int{3}, true) + + tree.Remove(Item3{Key: 3}) + assertValidTree(t, tree, 3) + assertItem3ValidTreeNode(t, tree.Root, 1, 2, []int{1}, false) + assertItem3ValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{0}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1], 1, 0, []int{2}, true) +} + +func TestBTreeRemove6(t *testing.T) { + // root height reduction after a series of underflows on right side + // use simulator: https://www.cs.usfca.edu/~galles/visualization/BTree.html + tree := NewWith(3) + tree.Put(Item3{Key: 1, Value: nil}) + tree.Put(Item3{Key: 2, Value: nil}) + tree.Put(Item3{Key: 3, Value: nil}) + tree.Put(Item3{Key: 4, Value: nil}) + tree.Put(Item3{Key: 5, Value: nil}) + tree.Put(Item3{Key: 6, Value: nil}) + tree.Put(Item3{Key: 7, Value: nil}) + + assertValidTree(t, tree, 7) + assertItem3ValidTreeNode(t, tree.Root, 1, 2, []int{4}, false) + assertItem3ValidTreeNode(t, tree.Root.Children[0], 1, 2, []int{2}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1], 1, 2, []int{6}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[0].Children[0], 1, 0, []int{1}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[0].Children[1], 1, 0, []int{3}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1].Children[0], 1, 0, []int{5}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1].Children[1], 1, 0, []int{7}, true) + + tree.Remove(Item3{Key: 7}) + assertValidTree(t, tree, 6) + assertItem3ValidTreeNode(t, tree.Root, 2, 3, []int{2, 4}, false) + assertItem3ValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{1}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1], 1, 0, []int{3}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[2], 2, 0, []int{5, 6}, true) +} + +// +func TestBTreeRemove7(t *testing.T) { + // root height reduction after a series of underflows on left side + // use simulator: https://www.cs.usfca.edu/~galles/visualization/BTree.html + tree := NewWith(3) + tree.Put(Item3{Key: 1, Value: nil}) + tree.Put(Item3{Key: 2, Value: nil}) + tree.Put(Item3{Key: 3, Value: nil}) + tree.Put(Item3{Key: 4, Value: nil}) + tree.Put(Item3{Key: 5, Value: nil}) + tree.Put(Item3{Key: 6, Value: nil}) + tree.Put(Item3{Key: 7, Value: nil}) + + assertValidTree(t, tree, 7) + assertItem3ValidTreeNode(t, tree.Root, 1, 2, []int{4}, false) + assertItem3ValidTreeNode(t, tree.Root.Children[0], 1, 2, []int{2}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1], 1, 2, []int{6}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[0].Children[0], 1, 0, []int{1}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[0].Children[1], 1, 0, []int{3}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1].Children[0], 1, 0, []int{5}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1].Children[1], 1, 0, []int{7}, true) + + tree.Remove(Item3{Key: 1}) // series of underflows + assertValidTree(t, tree, 6) + assertItem3ValidTreeNode(t, tree.Root, 2, 3, []int{4, 6}, false) + assertItem3ValidTreeNode(t, tree.Root.Children[0], 2, 0, []int{2, 3}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1], 1, 0, []int{5}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[2], 1, 0, []int{7}, true) + + // clear all remaining + tree.Remove(Item3{Key: 2}) + assertValidTree(t, tree, 5) + assertItem3ValidTreeNode(t, tree.Root, 2, 3, []int{4, 6}, false) + assertItem3ValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{3}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1], 1, 0, []int{5}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[2], 1, 0, []int{7}, true) + + tree.Remove(Item3{Key: 3}) + assertValidTree(t, tree, 4) + assertItem3ValidTreeNode(t, tree.Root, 1, 2, []int{6}, false) + assertItem3ValidTreeNode(t, tree.Root.Children[0], 2, 0, []int{4, 5}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1], 1, 0, []int{7}, true) + + tree.Remove(Item3{Key: 4}) + assertValidTree(t, tree, 3) + assertItem3ValidTreeNode(t, tree.Root, 1, 2, []int{6}, false) + assertItem3ValidTreeNode(t, tree.Root.Children[0], 1, 0, []int{5}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1], 1, 0, []int{7}, true) + + tree.Remove(Item3{Key: 5}) + assertValidTree(t, tree, 2) + assertItem3ValidTreeNode(t, tree.Root, 2, 0, []int{6, 7}, false) + + tree.Remove(Item3{Key: 6}) + assertValidTree(t, tree, 1) + assertItem3ValidTreeNode(t, tree.Root, 1, 0, []int{7}, false) + + tree.Remove(Item3{Key: 7}) + assertValidTree(t, tree, 0) +} + +// +func TestBTreeRemove8(t *testing.T) { + // use simulator: https://www.cs.usfca.edu/~galles/visualization/BTree.html + tree := NewWith(3) + tree.Put(Item3{Key: 1, Value: nil}) + tree.Put(Item3{Key: 2, Value: nil}) + tree.Put(Item3{Key: 3, Value: nil}) + tree.Put(Item3{Key: 4, Value: nil}) + tree.Put(Item3{Key: 5, Value: nil}) + tree.Put(Item3{Key: 6, Value: nil}) + tree.Put(Item3{Key: 7, Value: nil}) + tree.Put(Item3{Key: 8, Value: nil}) + tree.Put(Item3{Key: 9, Value: nil}) + + assertValidTree(t, tree, 9) + assertItem3ValidTreeNode(t, tree.Root, 1, 2, []int{4}, false) + assertItem3ValidTreeNode(t, tree.Root.Children[0], 1, 2, []int{2}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1], 2, 3, []int{6, 8}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[0].Children[0], 1, 0, []int{1}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[0].Children[1], 1, 0, []int{3}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1].Children[0], 1, 0, []int{5}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1].Children[1], 1, 0, []int{7}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1].Children[2], 1, 0, []int{9}, true) + + tree.Remove(Item3{Key: 1}) + assertValidTree(t, tree, 8) + assertItem3ValidTreeNode(t, tree.Root, 1, 2, []int{6}, false) + assertItem3ValidTreeNode(t, tree.Root.Children[0], 1, 2, []int{4}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1], 1, 2, []int{8}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[0].Children[0], 2, 0, []int{2, 3}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[0].Children[1], 1, 0, []int{5}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1].Children[0], 1, 0, []int{7}, true) + assertItem3ValidTreeNode(t, tree.Root.Children[1].Children[1], 1, 0, []int{9}, true) +} + +func TestBTreeRemove9(t *testing.T) { + const max = 1000 + orders := []int{3, 4, 5, 6, 7, 8, 9, 10, 20, 100, 500, 1000, 5000, 10000} + for _, order := range orders { + + tree := NewWith(order) + + { + for i := 1; i <= max; i++ { + tree.Put(Item2{Key: i, Value: i}) + } + assertValidTree(t, tree, max) + + for i := 1; i <= max; i++ { + if _, found := tree.Get(Item2{Key: i}); !found { + t.Errorf("Not found %v", i) + } + } + + for i := 1; i <= max; i++ { + tree.Remove(Item2{Key: i}) + } + assertValidTree(t, tree, 0) + } + + { + for i := max; i > 0; i-- { + tree.Put(Item2{Key: i, Value: i}) + } + assertValidTree(t, tree, max) + + for i := max; i > 0; i-- { + if _, found := tree.Get(Item2{Key: i}); !found { + t.Errorf("Not found %v", i) + } + } + + for i := max; i > 0; i-- { + tree.Remove(Item2{Key: i}) + } + assertValidTree(t, tree, 0) + } + } +} + +func TestBTreeHeight(t *testing.T) { + tree := NewWith(3) + if actualValue, expectedValue := tree.Height(), 0; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + + tree.Put(Item2{Key: 1, Value: 0}) + if actualValue, expectedValue := tree.Height(), 1; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + + tree.Put(Item2{Key: 2, Value: 1}) + if actualValue, expectedValue := tree.Height(), 1; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + + tree.Put(Item2{Key: 3, Value: 2}) + if actualValue, expectedValue := tree.Height(), 2; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + + tree.Put(Item2{Key: 4, Value: 2}) + if actualValue, expectedValue := tree.Height(), 2; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + + tree.Put(Item2{Key: 5, Value: 2}) + if actualValue, expectedValue := tree.Height(), 2; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + + tree.Put(Item2{Key: 6, Value: 2}) + if actualValue, expectedValue := tree.Height(), 2; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + + tree.Put(Item2{Key: 7, Value: 2}) + if actualValue, expectedValue := tree.Height(), 3; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + + tree.Remove(Item2{Key: 1}) + tree.Remove(Item2{Key: 2}) + tree.Remove(Item2{Key: 3}) + tree.Remove(Item2{Key: 4}) + tree.Remove(Item2{Key: 5}) + tree.Remove(Item2{Key: 6}) + tree.Remove(Item2{Key: 7}) + if actualValue, expectedValue := tree.Height(), 0; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } +} + +func TestBTreeLeftAndRight(t *testing.T) { + tree := NewWith(3) + + if actualValue := tree.Left(); actualValue != nil { + t.Errorf("Got %v expected %v", actualValue, nil) + } + if actualValue := tree.Right(); actualValue != nil { + t.Errorf("Got %v expected %v", actualValue, nil) + } + + tree.Put(Item{Key: 1, Value: "a"}) + tree.Put(Item{Key: 5, Value: "e"}) + tree.Put(Item{Key: 6, Value: "f"}) + tree.Put(Item{Key: 7, Value: "g"}) + tree.Put(Item{Key: 3, Value: "c"}) + tree.Put(Item{Key: 4, Value: "d"}) + tree.Put(Item{Key: 1, Value: "x"}) // overwrite + tree.Put(Item{Key: 2, Value: "b"}) + + if actualValue, expectedValue := tree.LeftItem(), 1; actualValue.(Item).Key != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue, expectedValue := tree.LeftItem(), "x"; actualValue.(Item).Value != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + + if actualValue, expectedValue := tree.RightItem(), 7; actualValue.(Item).Key != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue, expectedValue := tree.RightItem(), "g"; actualValue.(Item).Value != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } +} + +func TestBTreeIteratorValuesAndKeys(t *testing.T) { + tree := NewWith(4) + tree.Put(Item{Key: 4, Value: "d"}) + tree.Put(Item{Key: 5, Value: "e"}) + tree.Put(Item{Key: 6, Value: "f"}) + tree.Put(Item{Key: 3, Value: "c"}) + tree.Put(Item{Key: 1, Value: "a"}) + tree.Put(Item{Key: 7, Value: "g"}) + tree.Put(Item{Key: 2, Value: "b"}) + tree.Put(Item{Key: 1, Value: "x"}) // override + + contents := tree.Contents() + var keys []interface{} + var values []interface{} + for _, content := range contents { + keys = append(keys, content.(Item).Key) + values = append(values, content.(Item).Value) + } + + if actualValue, expectedValue := fmt.Sprintf("%d%d%d%d%d%d%d", keys...), "1234567"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue, expectedValue := fmt.Sprintf("%s%s%s%s%s%s%s", values...), "xbcdefg"; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue := tree.Size(); actualValue != 7 { + t.Errorf("Got %v expected %v", actualValue, 7) + } +} + +func TestBTreeIteratorNextOnEmpty(t *testing.T) { + tree := NewWith(3) + it := tree.Iterator() + for it.Next() { + t.Errorf("Shouldn't iterate on empty tree") + } +} + +// +func TestBTreeIteratorPrevOnEmpty(t *testing.T) { + tree := NewWith(3) + it := tree.Iterator() + for it.Prev() { + t.Errorf("Shouldn't iterate on empty tree") + } +} + +func TestBTreeIterator1Next(t *testing.T) { + tree := NewWith(3) + tree.Put(Item{Key: 5, Value: "e"}) + tree.Put(Item{Key: 6, Value: "f"}) + tree.Put(Item{Key: 7, Value: "g"}) + tree.Put(Item{Key: 3, Value: "c"}) + tree.Put(Item{Key: 4, Value: "d"}) + tree.Put(Item{Key: 1, Value: "x"}) + tree.Put(Item{Key: 2, Value: "b"}) + tree.Put(Item{Key: 1, Value: "a"}) //overwrite + it := tree.Iterator() + count := 0 + for it.Next() { + count++ + Key := it.Item().(Item).Key + switch Key { + case count: + if actualValue, expectedValue := Key, count; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + default: + if actualValue, expectedValue := Key, count; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + } + } + if actualValue, expectedValue := count, tree.Size(); actualValue != expectedValue { + t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue) + } +} + +// +func TestBTreeIterator1Prev(t *testing.T) { + tree := NewWith(3) + tree.Put(Item{Key: 5, Value: "e"}) + tree.Put(Item{Key: 6, Value: "f"}) + tree.Put(Item{Key: 7, Value: "g"}) + tree.Put(Item{Key: 3, Value: "c"}) + tree.Put(Item{Key: 4, Value: "d"}) + tree.Put(Item{Key: 1, Value: "x"}) + tree.Put(Item{Key: 2, Value: "b"}) + tree.Put(Item{Key: 1, Value: "a"}) //overwrite + it := tree.Iterator() + for it.Next() { + } + countDown := tree.size + for it.Prev() { + Key := it.Item().(Item).Key + switch Key { + case countDown: + if actualValue, expectedValue := Key, countDown; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + default: + if actualValue, expectedValue := Key, countDown; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + } + countDown-- + } + if actualValue, expectedValue := countDown, 0; actualValue != expectedValue { + t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue) + } +} + +func TestBTreeIterator2Next(t *testing.T) { + tree := NewWith(3) + tree.Put(Item{Key: 3, Value: "c"}) + tree.Put(Item{Key: 1, Value: "a"}) + tree.Put(Item{Key: 2, Value: "b"}) + it := tree.Iterator() + count := 0 + for it.Next() { + count++ + Key := it.Item().(Item).Key + switch Key { + case count: + if actualValue, expectedValue := Key, count; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + default: + if actualValue, expectedValue := Key, count; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + } + } + if actualValue, expectedValue := count, tree.Size(); actualValue != expectedValue { + t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue) + } +} + +// +func TestBTreeIterator2Prev(t *testing.T) { + tree := NewWith(3) + tree.Put(Item{Key: 3, Value: "c"}) + tree.Put(Item{Key: 1, Value: "a"}) + tree.Put(Item{Key: 2, Value: "b"}) + it := tree.Iterator() + for it.Next() { + } + countDown := tree.size + for it.Prev() { + Key := it.Item().(Item).Key + switch Key { + case countDown: + if actualValue, expectedValue := Key, countDown; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + default: + if actualValue, expectedValue := Key, countDown; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + } + countDown-- + } + if actualValue, expectedValue := countDown, 0; actualValue != expectedValue { + t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue) + } +} + +func TestBTreeIterator3Next(t *testing.T) { + tree := NewWith(3) + tree.Put(Item{Key: 1, Value: "a"}) + it := tree.Iterator() + count := 0 + for it.Next() { + count++ + Key := it.Item().(Item).Key + switch Key { + case count: + if actualValue, expectedValue := Key, count; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + default: + if actualValue, expectedValue := Key, count; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + } + } + if actualValue, expectedValue := count, tree.Size(); actualValue != expectedValue { + t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue) + } +} + +func TestBTreeIterator3Prev(t *testing.T) { + tree := NewWith(3) + tree.Put(Item{Key: 1, Value: "a"}) + it := tree.Iterator() + for it.Next() { + } + countDown := tree.size + for it.Prev() { + Key := it.Item().(Item).Key + switch Key { + case countDown: + if actualValue, expectedValue := Key, countDown; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + default: + if actualValue, expectedValue := Key, countDown; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + } + countDown-- + } + if actualValue, expectedValue := countDown, 0; actualValue != expectedValue { + t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue) + } +} + +func TestBTreeIterator4Next(t *testing.T) { + tree := NewWith(3) + tree.Put(Item2{Key: 13, Value: 5}) + tree.Put(Item2{Key: 8, Value: 3}) + tree.Put(Item2{Key: 17, Value: 7}) + tree.Put(Item2{Key: 1, Value: 1}) + tree.Put(Item2{Key: 11, Value: 4}) + tree.Put(Item2{Key: 15, Value: 6}) + tree.Put(Item2{Key: 25, Value: 9}) + tree.Put(Item2{Key: 6, Value: 2}) + tree.Put(Item2{Key: 22, Value: 8}) + tree.Put(Item2{Key: 27, Value: 10}) + it := tree.Iterator() + count := 0 + for it.Next() { + count++ + Value := it.Item().(Item2).Value + switch Value { + case count: + if actualValue, expectedValue := Value, count; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + default: + if actualValue, expectedValue := Value, count; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + } + } + if actualValue, expectedValue := count, tree.Size(); actualValue != expectedValue { + t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue) + } +} + +func TestBTreeIterator4Prev(t *testing.T) { + tree := NewWith(3) + tree.Put(Item2{Key: 13, Value: 5}) + tree.Put(Item2{Key: 8, Value: 3}) + tree.Put(Item2{Key: 17, Value: 7}) + tree.Put(Item2{Key: 1, Value: 1}) + tree.Put(Item2{Key: 11, Value: 4}) + tree.Put(Item2{Key: 15, Value: 6}) + tree.Put(Item2{Key: 25, Value: 9}) + tree.Put(Item2{Key: 6, Value: 2}) + tree.Put(Item2{Key: 22, Value: 8}) + tree.Put(Item2{Key: 27, Value: 10}) + it := tree.Iterator() + count := tree.Size() + for it.Next() { + } + for it.Prev() { + Value := it.Item().(Item2).Value + switch Value { + case count: + if actualValue, expectedValue := Value, count; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + default: + if actualValue, expectedValue := Value, count; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + } + count-- + } + if actualValue, expectedValue := count, 0; actualValue != expectedValue { + t.Errorf("Size different. Got %v expected %v", actualValue, expectedValue) + } +} + +func TestBTreeIteratorBegin(t *testing.T) { + tree := NewWith(3) + tree.Put(Item{Key: 3, Value: "c"}) + tree.Put(Item{Key: 1, Value: "a"}) + tree.Put(Item{Key: 2, Value: "b"}) + it := tree.Iterator() + + if it.node != nil { + t.Errorf("Got %v expected %v", it.node, nil) + } + + it.Begin() + + if it.node != nil { + t.Errorf("Got %v expected %v", it.node, nil) + } + + for it.Next() { + } + + it.Begin() + + if it.node != nil { + t.Errorf("Got %v expected %v", it.node, nil) + } + + it.Next() + if Key, Value := it.Item().(Item).Key, it.Item().(Item).Value; Key != 1 || Value != "a" { + t.Errorf("Got %v,%v expected %v,%v", Key, Value, 1, "a") + } +} + +func TestBTreeIteratorEnd(t *testing.T) { + tree := NewWith(3) + it := tree.Iterator() + + if it.node != nil { + t.Errorf("Got %v expected %v", it.node, nil) + } + + it.End() + if it.node != nil { + t.Errorf("Got %v expected %v", it.node, nil) + } + + tree.Put(Item{Key: 3, Value: "c"}) + tree.Put(Item{Key: 1, Value: "a"}) + tree.Put(Item{Key: 2, Value: "b"}) + it.End() + if it.node != nil { + t.Errorf("Got %v expected %v", it.node, nil) + } + + it.Prev() + if Key, Value := it.Item().(Item).Key, it.Item().(Item).Value; Key != 3 || Value != "c" { + t.Errorf("Got %v,%v expected %v,%v", Key, Value, 3, "c") + } +} + +// +func TestBTreeIteratorFirst(t *testing.T) { + tree := NewWith(3) + tree.Put(Item{Key: 3, Value: "c"}) + tree.Put(Item{Key: 1, Value: "a"}) + tree.Put(Item{Key: 2, Value: "b"}) + it := tree.Iterator() + if actualValue, expectedValue := it.First(), true; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if Key, Value := it.Item().(Item).Key, it.Item().(Item).Value; Key != 1 || Value != "a" { + t.Errorf("Got %v,%v expected %v,%v", Key, Value, 1, "a") + } +} + +func TestBTreeIteratorLast(t *testing.T) { + tree := NewWith(3) + tree.Put(Item{Key: 3, Value: "c"}) + tree.Put(Item{Key: 1, Value: "a"}) + tree.Put(Item{Key: 2, Value: "b"}) + it := tree.Iterator() + if actualValue, expectedValue := it.Last(), true; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if Key, Value := it.Item().(Item).Key, it.Item().(Item).Value; Key != 3 || Value != "c" { + t.Errorf("Got %v,%v expected %v,%v", Key, Value, 3, "c") + } +} + +// +func TestBTree_search(t *testing.T) { + { + tree := NewWith(3) + tree.Root = &Node{Contents: []*Content{}, Children: make([]*Node, 0)} + tests := [][]interface{}{ + {0, 0, false}, + } + for _, test := range tests { + index, found := tree.search(tree.Root, Item3{Key: test[0].(int)}) + if actualValue, expectedValue := index, test[1]; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue, expectedValue := found, test[2]; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + } + } + { + tree := NewWith(3) + var node Node + node.Put(Item2{Key: 2, Value: 0}) + node.Put(Item2{Key: 4, Value: 1}) + node.Put(Item2{Key: 6, Value: 2}) + node.Children = []*Node{} + tree.Root = &node + tests := [][]interface{}{ + {0, 0, false}, + {1, 0, false}, + {2, 0, true}, + {3, 1, false}, + {4, 1, true}, + {5, 2, false}, + {6, 2, true}, + {7, 3, false}, + } + for _, test := range tests { + index, found := tree.search(tree.Root, Item2{Key: test[0].(int)}) + if actualValue, expectedValue := index, test[1].(int); actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + if actualValue, expectedValue := found, test[2]; actualValue != expectedValue { + t.Errorf("Got %v expected %v", actualValue, expectedValue) + } + } + } +} + +func assertValidTree(t *testing.T, tree *Tree, expectedSize int) { + if actualValue, expectedValue := tree.size, expectedSize; actualValue != expectedValue { + t.Errorf("Got %v expected %v for tree size", actualValue, expectedValue) + } +} + +// +func assertValidTreeNode(t *testing.T, node *Node, expectedContents int, expectedChildren int, keys []int, hasParent bool) { + if actualValue, expectedValue := node.Parent != nil, hasParent; actualValue != expectedValue { + t.Errorf("Got %v expected %v for hasParent", actualValue, expectedValue) + } + if actualValue, expectedValue := len(node.Contents), expectedContents; actualValue != expectedValue { + t.Errorf("Got %v expected %v for contents size", actualValue, expectedValue) + } + if actualValue, expectedValue := len(node.Children), expectedChildren; actualValue != expectedValue { + t.Errorf("Got %v expected %v for children size", actualValue, expectedValue) + } + for i, Key := range keys { + if actualValue, expectedValue := (*node.Contents[i]).(Item2).Key, Key; actualValue != expectedValue { + t.Errorf("Got %v expected %v for Key", actualValue, expectedValue) + } + } +} + +func assertItem3ValidTreeNode(t *testing.T, node *Node, expectedContents int, expectedChildren int, keys []int, hasParent bool) { + if actualValue, expectedValue := node.Parent != nil, hasParent; actualValue != expectedValue { + t.Errorf("Got %v expected %v for hasParent", actualValue, expectedValue) + } + if actualValue, expectedValue := len(node.Contents), expectedContents; actualValue != expectedValue { + t.Errorf("Got %v expected %v for contents size", actualValue, expectedValue) + } + if actualValue, expectedValue := len(node.Children), expectedChildren; actualValue != expectedValue { + t.Errorf("Got %v expected %v for children size", actualValue, expectedValue) + } + for i, Key := range keys { + if actualValue, expectedValue := (*node.Contents[i]).(Item3).Key, Key; actualValue != expectedValue { + t.Errorf("Got %v expected %v for Key", actualValue, expectedValue) + } + } +} + +func benchmarkGet(b *testing.B, tree *Tree, size int) { + for i := 0; i < b.N; i++ { + for n := 0; n < size; n++ { + tree.Get(Item3{Key: n}) + } + } +} + +func benchmarkPut(b *testing.B, tree *Tree, size int) { + for i := 0; i < b.N; i++ { + for n := 0; n < size; n++ { + tree.Put(Item3{Key: n, Value: struct{}{}}) + } + } +} + +// +func benchmarkRemove(b *testing.B, tree *Tree, size int) { + for i := 0; i < b.N; i++ { + for n := 0; n < size; n++ { + tree.Remove(Item3{Key: n}) + } + } +} + +func BenchmarkBTreeGet100(b *testing.B) { + b.StopTimer() + size := 100 + tree := NewWith(128) + for n := 0; n < size; n++ { + tree.Put(Item3{Key: n, Value: struct{}{}}) + } + b.StartTimer() + benchmarkGet(b, tree, size) +} + +func BenchmarkBTreeGet1000(b *testing.B) { + b.StopTimer() + size := 1000 + tree := NewWith(128) + for n := 0; n < size; n++ { + tree.Put(Item3{Key: n, Value: struct{}{}}) + } + b.StartTimer() + benchmarkGet(b, tree, size) +} + +func BenchmarkBTreeGet10000(b *testing.B) { + b.StopTimer() + size := 10000 + tree := NewWith(128) + for n := 0; n < size; n++ { + tree.Put(Item3{Key: n, Value: struct{}{}}) + } + b.StartTimer() + benchmarkGet(b, tree, size) +} + +// +func BenchmarkBTreeGet100000(b *testing.B) { + b.StopTimer() + size := 100000 + tree := NewWith(128) + for n := 0; n < size; n++ { + tree.Put(Item3{Key: n, Value: struct{}{}}) + } + b.StartTimer() + benchmarkGet(b, tree, size) +} + +func BenchmarkBTreePut100(b *testing.B) { + b.StopTimer() + size := 100 + tree := NewWith(128) + b.StartTimer() + benchmarkPut(b, tree, size) +} + +func BenchmarkBTreePut1000(b *testing.B) { + b.StopTimer() + size := 1000 + tree := NewWith(128) + for n := 0; n < size; n++ { + tree.Put(Item3{Key: n, Value: struct{}{}}) + } + b.StartTimer() + benchmarkPut(b, tree, size) +} + +// +func BenchmarkBTreePut10000(b *testing.B) { + b.StopTimer() + size := 10000 + tree := NewWith(128) + for n := 0; n < size; n++ { + tree.Put(Item3{Key: n, Value: struct{}{}}) + } + b.StartTimer() + benchmarkPut(b, tree, size) +} + +// +func BenchmarkBTreePut100000(b *testing.B) { + b.StopTimer() + size := 100000 + tree := NewWith(128) + for n := 0; n < size; n++ { + tree.Put(Item3{Key: n, Value: struct{}{}}) + } + b.StartTimer() + benchmarkPut(b, tree, size) +} + +func BenchmarkBTreeRemove100(b *testing.B) { + b.StopTimer() + size := 100 + tree := NewWith(128) + for n := 0; n < size; n++ { + tree.Put(Item3{Key: n, Value: struct{}{}}) + } + b.StartTimer() + benchmarkRemove(b, tree, size) +} + +// +func BenchmarkBTreeRemove1000(b *testing.B) { + b.StopTimer() + size := 1000 + tree := NewWith(128) + for n := 0; n < size; n++ { + tree.Put(Item3{Key: n, Value: struct{}{}}) + } + b.StartTimer() + benchmarkRemove(b, tree, size) +} + +// +func BenchmarkBTreeRemove10000(b *testing.B) { + b.StopTimer() + size := 10000 + tree := NewWith(128) + for n := 0; n < size; n++ { + tree.Put(Item3{Key: n, Value: struct{}{}}) + } + b.StartTimer() + benchmarkRemove(b, tree, size) +} + +func BenchmarkBTreeRemove100000(b *testing.B) { + b.StopTimer() + size := 100000 + tree := NewWith(128) + for n := 0; n < size; n++ { + tree.Put(Item3{Key: n, Value: struct{}{}}) + } + b.StartTimer() + benchmarkRemove(b, tree, size) +} diff --git a/merklebtree/iterator.go b/merklebtree/iterator.go new file mode 100644 index 0000000..eab6d91 --- /dev/null +++ b/merklebtree/iterator.go @@ -0,0 +1,181 @@ +// Copyright (c) 2015, Emir Pasic. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package merklebtree + +// Iterator holding the iterator's state +type Iterator struct { + tree *Tree + node *Node + entry *Content + position position +} + +type position byte + +const ( + begin, between, end position = 0, 1, 2 +) + +// Iterator returns a stateful iterator whose elements are key/value pairs. +func (tree *Tree) Iterator() Iterator { + return Iterator{tree: tree, node: nil, position: begin} +} + +// Next moves the iterator to the next element and returns true if there was a next element in the container. +// If Next() returns true, then next element's key and value can be retrieved by Key() and Value(). +// If Next() was called for the first time, then it will point the iterator to the first element if it exists. +// Modifies the state of the iterator. +func (iterator *Iterator) Next() bool { + // If already at end, go to end + if iterator.position == end { + goto end + } + // If at beginning, get the left-most entry in the tree + if iterator.position == begin { + left := iterator.tree.Left() + if left == nil { + goto end + } + iterator.node = left + iterator.entry = left.Contents[0] + goto between + } + { + // Find current entry position in current node + e, _ := iterator.tree.search(iterator.node, *iterator.entry) + // Try to go down to the child right of the current entry + if e+1 < len(iterator.node.Children) { + iterator.node = iterator.node.Children[e+1] + // Try to go down to the child left of the current node + for len(iterator.node.Children) > 0 { + iterator.node = iterator.node.Children[0] + } + // Return the left-most entry + iterator.entry = iterator.node.Contents[0] + goto between + } + // Above assures that we have reached a leaf node, so return the next entry in current node (if any) + if e+1 < len(iterator.node.Contents) { + iterator.entry = iterator.node.Contents[e+1] + goto between + } + } + // Reached leaf node and there are no contents to the right of the current entry, so go up to the parent + for iterator.node.Parent != nil { + iterator.node = iterator.node.Parent + // Find next entry position in current node (note: search returns the first equal or bigger than entry) + e, _ := iterator.tree.search(iterator.node, *iterator.entry) + // Check that there is a next entry position in current node + if e < len(iterator.node.Contents) { + iterator.entry = iterator.node.Contents[e] + goto between + } + } + +end: + iterator.End() + return false + +between: + iterator.position = between + return true +} + +// Prev moves the iterator to the previous element and returns true if there was a previous element in the container. +// If Prev() returns true, then previous element's key and value can be retrieved by Key() and Value(). +// Modifies the state of the iterator. +func (iterator *Iterator) Prev() bool { + // If already at beginning, go to begin + if iterator.position == begin { + goto begin + } + // If at end, get the right-most entry in the tree + if iterator.position == end { + right := iterator.tree.Right() + if right == nil { + goto begin + } + iterator.node = right + iterator.entry = right.Contents[len(right.Contents)-1] + goto between + } + { + // Find current entry position in current node + e, _ := iterator.tree.search(iterator.node, *iterator.entry) + // Try to go down to the child left of the current entry + if e < len(iterator.node.Children) { + iterator.node = iterator.node.Children[e] + // Try to go down to the child right of the current node + for len(iterator.node.Children) > 0 { + iterator.node = iterator.node.Children[len(iterator.node.Children)-1] + } + // Return the right-most entry + iterator.entry = iterator.node.Contents[len(iterator.node.Contents)-1] + goto between + } + // Above assures that we have reached a leaf node, so return the previous entry in current node (if any) + if e-1 >= 0 { + iterator.entry = iterator.node.Contents[e-1] + goto between + } + } + // Reached leaf node and there are no contents to the left of the current entry, so go up to the parent + for iterator.node.Parent != nil { + iterator.node = iterator.node.Parent + // Find previous entry position in current node (note: search returns the first equal or bigger than entry) + e, _ := iterator.tree.search(iterator.node, *iterator.entry) + // Check that there is a previous entry position in current node + if e-1 >= 0 { + iterator.entry = iterator.node.Contents[e-1] + goto between + } + } + +begin: + iterator.Begin() + return false + +between: + iterator.position = between + return true +} + +// Key returns the current element's key. +// Does not modify the state of the iterator. +func (iterator *Iterator) Item() Content { + return *iterator.entry +} + +// Begin resets the iterator to its initial state (one-before-first) +// Call Next() to fetch the first element if any. +func (iterator *Iterator) Begin() { + iterator.node = nil + iterator.position = begin + iterator.entry = nil +} + +// End moves the iterator past the last element (one-past-the-end). +// Call Prev() to fetch the last element if any. +func (iterator *Iterator) End() { + iterator.node = nil + iterator.position = end + iterator.entry = nil +} + +// First moves the iterator to the first element and returns true if there was a first element in the container. +// If First() returns true, then first element's key and value can be retrieved by Key() and Value(). +// Modifies the state of the iterator +func (iterator *Iterator) First() bool { + iterator.Begin() + return iterator.Next() +} + +// Last moves the iterator to the last element and returns true if there was a last element in the container. +// If Last() returns true, then last element's key and value can be retrieved by Key() and Value(). +// Modifies the state of the iterator. +func (iterator *Iterator) Last() bool { + iterator.End() + return iterator.Prev() +} diff --git a/merklebtree/mbtree_test.go b/merklebtree/mbtree_test.go new file mode 100644 index 0000000..3becc94 --- /dev/null +++ b/merklebtree/mbtree_test.go @@ -0,0 +1,80 @@ +package merklebtree + +import ( + "strings" + "testing" +) + +func TestMBTreePut1(t *testing.T) { + tree := NewWith(3) + tree.Put(Item2{Key: 1, Value: 0}) + assertValidMerkleRoot(t, tree.MerkleBTreeRoot(), tree.calculateMerkleRoot()) + + tree.Put(Item2{Key: 2, Value: 1}) + assertValidMerkleRoot(t, tree.MerkleBTreeRoot(), tree.calculateMerkleRoot()) + + //replace root node + tree.Put(Item2{Key: 1, Value: 3}) + assertValidMerkleRoot(t, tree.MerkleBTreeRoot(), tree.calculateMerkleRoot()) + + //split root node + tree.Put(Item2{Key: 3, Value: 6}) + assertValidMerkleRoot(t, tree.MerkleBTreeRoot(), tree.calculateMerkleRoot()) + + //replace leaf node + tree.Put(Item2{Key: 2, Value: 5}) + assertValidMerkleRoot(t, tree.MerkleBTreeRoot(), tree.calculateMerkleRoot()) + + tree.Put(Item2{Key: 4, Value: 2}) + assertValidMerkleRoot(t, tree.MerkleBTreeRoot(), tree.calculateMerkleRoot()) + + tree.Put(Item2{Key: 5, Value: 2}) + assertValidMerkleRoot(t, tree.MerkleBTreeRoot(), tree.calculateMerkleRoot()) + + tree.Put(Item2{Key: 6, Value: 2}) + assertValidMerkleRoot(t, tree.MerkleBTreeRoot(), tree.calculateMerkleRoot()) + + tree.Put(Item2{Key: 7, Value: 2}) + assertValidMerkleRoot(t, tree.MerkleBTreeRoot(), tree.calculateMerkleRoot()) +} + +func TestMBTreePut2(t *testing.T) { + const max = 1000 + orders := []int{3, 4, 5, 6, 7, 8, 9, 10, 20, 100, 500} + for _, order := range orders { + tree := NewWith(order) + { + for i := 1; i <= max; i++ { + tree.Put(Item2{Key: i, Value: i}) + assertValidMerkleRoot(t, tree.MerkleBTreeRoot(), tree.calculateMerkleRoot()) + } + + } + { + for i := max; i > 0; i-- { + tree.Remove(Item2{Key: i}) + assertValidMerkleRoot(t, tree.MerkleBTreeRoot(), tree.calculateMerkleRoot()) + } + } + } +} + +func TestMBTreeRemove1(t *testing.T){ + tree := NewWith(3) + tree.Put(Item2{Key: 1, Value: 0}) + tree.Put(Item2{Key: 2, Value: 1}) + tree.Put(Item2{Key: 1, Value: 3}) + tree.Put(Item2{Key: 3, Value: 6}) + tree.Put(Item2{Key: 2, Value: 5}) + tree.Put(Item2{Key: 4, Value: 2}) + tree.Put(Item2{Key: 5, Value: 2}) + tree.Put(Item2{Key: 6, Value: 2}) + assertValidMerkleRoot(t, tree.MerkleBTreeRoot(), tree.calculateMerkleRoot()) + +} + +func assertValidMerkleRoot(t *testing.T, str1 string, str2 string) { + if strings.Compare(str1, str2) != 0 { + t.Errorf("Got %v expected %v for MerkleRoot", str1, str2) + } +} \ No newline at end of file