/** * Copyright 2013 Benjamin Lerer * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.horizondb.db.btree; import io.horizondb.test.AssertCollections; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.junit.After; import org.junit.Before; import org.junit.Test; import static io.horizondb.db.btree.AssertNodes.assertInternalNode; import static io.horizondb.db.btree.AssertNodes.assertLeafNodeContains; import static io.horizondb.db.btree.AssertNodes.assertLeafNodeEmpty; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; public class BTreeTest { /** * The manager used during the tests. */ private NodeManager<Integer, String> manager; @Before public void setUp() { this.manager = new InMemoryNodeManager<Integer, String>("testManager"); } @After public void tearDown() { this.manager = null; } @Test @SuppressWarnings({ "boxing" }) public void testInsertionWithOnlyARootNode() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(2, "B"); assertLeafNodeContains(btree.getRoot(), 2, "B"); btree.insert(4, "D"); assertLeafNodeContains(btree.getRoot(), 2, "B", 4, "D"); btree.insert(3, "C"); assertLeafNodeContains(btree.getRoot(), 2, "B", 3, "C", 4, "D"); btree.insert(1, "A"); assertLeafNodeContains(btree.getRoot(), 1, "A", 2, "B", 3, "C", 4, "D"); } @Test @SuppressWarnings({ "boxing" }) public void testInsertingExistingKeyWithdOnlyARootNode() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(2, "B"); btree.insert(3, "D"); btree.insert(1, "A"); assertLeafNodeContains(btree.getRoot(), 1, "A", 2, "B", 3, "D"); btree.insert(3, "C"); assertLeafNodeContains(btree.getRoot(), 1, "A", 2, "B", 3, "C"); } @Test @SuppressWarnings({ "boxing" }) public void testGetWithOnlyARootNode() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(2, "B"); btree.insert(4, "D"); btree.insert(3, "C"); btree.insert(1, "A"); assertEquals("C", btree.get(3)); assertEquals("B", btree.get(2)); assertEquals("A", btree.get(1)); assertNull(btree.get(5)); } @Test @SuppressWarnings({ "boxing" }) public void testContainsWithOnlyARootNode() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(2, "B"); btree.insert(4, "D"); btree.insert(3, "C"); btree.insert(1, "A"); assertTrue(btree.contains(3)); assertTrue(btree.contains(2)); assertTrue(btree.contains(1)); assertFalse(btree.contains(10)); } @Test @SuppressWarnings({ "boxing" }) public void testDeletionWithOnlyARootNode() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(2, "B"); btree.insert(4, "D"); btree.insert(3, "C"); btree.insert(1, "A"); btree.delete(1); assertLeafNodeContains(btree.getRoot(), 2, "B", 3, "C", 4, "D"); btree.delete(3); assertLeafNodeContains(btree.getRoot(), 2, "B", 4, "D"); btree.delete(2); assertLeafNodeContains(btree.getRoot(), 4, "D"); btree.delete(2); assertLeafNodeContains(btree.getRoot(), 4, "D"); btree.delete(4); assertLeafNodeEmpty(btree.getRoot()); } @Test @SuppressWarnings({ "boxing" }) public void testIteratorWithOnlyARootNodeAndFullScan() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(2, "B"); btree.insert(4, "D"); btree.insert(3, "C"); btree.insert(1, "A"); KeyValueIterator<Integer, String> iterator = btree.iterator(0, 5); assertNextContains(iterator, 1, "A"); assertNextContains(iterator, 2, "B"); assertNextContains(iterator, 3, "C"); assertNextContains(iterator, 4, "D"); assertFalse(iterator.next()); } @Test @SuppressWarnings({ "boxing" }) public void testIteratorWithOnlyARootNodeAndPartialScan() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(2, "B"); btree.insert(4, "D"); btree.insert(3, "C"); btree.insert(1, "A"); KeyValueIterator<Integer, String> iterator = btree.iterator(2, 3); assertNextContains(iterator, 2, "B"); assertNextContains(iterator, 3, "C"); assertFalse(iterator.next()); } @Test @SuppressWarnings({ "boxing" }) public void testInsertionWithRootNodeSplit() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(2, "B"); btree.insert(4, "D"); btree.insert(3, "C"); btree.insert(1, "A"); btree.insert(6, "E"); assertInternalNode(btree.getRoot(), 1, 3); InternalNode<Integer, String> internalNode = (InternalNode<Integer, String>) btree.getRoot(); assertLeafNodeContains(internalNode.getChild(0), 1, "A", 2, "B"); assertLeafNodeContains(internalNode.getChild(1), 3, "C", 4, "D", 6, "E"); } @Test @SuppressWarnings({ "boxing" }) public void testInsertingExistingKeyWithInternalNodes() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(2, "B"); btree.insert(4, "D"); btree.insert(3, "C"); btree.insert(1, "A"); btree.insert(6, "F"); btree.insert(6, "E"); assertInternalNode(btree.getRoot(), 1, 3); InternalNode<Integer, String> internalNode = (InternalNode<Integer, String>) btree.getRoot(); assertLeafNodeContains(internalNode.getChild(0), 1, "A", 2, "B"); assertLeafNodeContains(internalNode.getChild(1), 3, "C", 4, "D", 6, "E"); } @Test @SuppressWarnings({ "boxing" }) public void testIteratorWithInternalNodesAndPartialScanOverTwoNodes() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(2, "B"); btree.insert(4, "D"); btree.insert(3, "C"); btree.insert(1, "A"); btree.insert(6, "F"); KeyValueIterator<Integer, String> iterator = btree.iterator(2, 3); assertNextContains(iterator, 2, "B"); assertNextContains(iterator, 3, "C"); assertFalse(iterator.next()); } @Test @SuppressWarnings({ "boxing" }) public void testIteratorWithInternalNodesAndPartialScanOverOneNode() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(2, "B"); btree.insert(4, "D"); btree.insert(3, "C"); btree.insert(1, "A"); btree.insert(6, "F"); KeyValueIterator<Integer, String> iterator = btree.iterator(1, 1); assertNextContains(iterator, 1, "A"); assertFalse(iterator.next()); } @Test @SuppressWarnings({ "boxing" }) public void testIteratorWithInternalNodesAndFullScan() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(2, "B"); btree.insert(4, "D"); btree.insert(3, "C"); btree.insert(1, "A"); btree.insert(6, "F"); KeyValueIterator<Integer, String> iterator = btree.iterator(0, 10); assertNextContains(iterator, 1, "A"); assertNextContains(iterator, 2, "B"); assertNextContains(iterator, 3, "C"); assertNextContains(iterator, 4, "D"); assertNextContains(iterator, 6, "F"); assertFalse(iterator.next()); } @Test @SuppressWarnings({ "boxing" }) public void testDeletionWithInternalNode() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(2, "B"); btree.insert(4, "D"); btree.insert(3, "C"); btree.insert(1, "A"); btree.insert(6, "E"); btree.delete(4); assertInternalNode(btree.getRoot(), 1, 3); InternalNode<Integer, String> internalNode = (InternalNode<Integer, String>) btree.getRoot(); assertLeafNodeContains(internalNode.getChild(0), 1, "A", 2, "B"); assertLeafNodeContains(internalNode.getChild(1), 3, "C", 6, "E"); } @Test @SuppressWarnings({ "boxing" }) public void testDeletionOfFirstKeyOfLeafNode() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(2, "B"); btree.insert(4, "D"); btree.insert(3, "C"); btree.insert(1, "A"); btree.insert(6, "E"); btree.delete(3); assertInternalNode(btree.getRoot(), 1, 4); InternalNode<Integer, String> internalNode = (InternalNode<Integer, String>) btree.getRoot(); assertLeafNodeContains(internalNode.getChild(0), 1, "A", 2, "B"); assertLeafNodeContains(internalNode.getChild(1), 4, "D", 6, "E"); } @Test @SuppressWarnings({ "boxing" }) public void testInsertionWithRootNodeSplitAndBranchingFactor4() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 4); btree.insert(2, "B"); btree.insert(4, "D"); btree.insert(3, "C"); btree.insert(1, "A"); assertInternalNode(btree.getRoot(), 1, 3); InternalNode<Integer, String> internalNode = (InternalNode<Integer, String>) btree.getRoot(); assertLeafNodeContains(internalNode.getChild(0), 1, "A", 2, "B"); assertLeafNodeContains(internalNode.getChild(1), 3, "C", 4, "D"); } @Test @SuppressWarnings({ "boxing" }) public void testInsertionOnLeftLeafNode() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(2, "B"); btree.insert(4, "D"); btree.insert(3, "C"); btree.insert(6, "F"); btree.insert(5, "E"); btree.insert(1, "A"); assertInternalNode(btree.getRoot(), 1, 4); InternalNode<Integer, String> internalNode = (InternalNode<Integer, String>) btree.getRoot(); assertLeafNodeContains(internalNode.getChild(0), 1, "A", 2, "B", 3, "C"); assertLeafNodeContains(internalNode.getChild(1), 4, "D", 5, "E", 6, "F"); } @Test @SuppressWarnings({ "boxing" }) public void testInsertionOnRightLeafNode() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(2, "B"); btree.insert(4, "D"); btree.insert(3, "C"); btree.insert(6, "F"); btree.insert(5, "E"); btree.insert(7, "G"); assertInternalNode(btree.getRoot(), 2, 4); InternalNode<Integer, String> internalNode = (InternalNode<Integer, String>) btree.getRoot(); assertLeafNodeContains(internalNode.getChild(0), 2, "B", 3, "C"); assertLeafNodeContains(internalNode.getChild(1), 4, "D", 5, "E", 6, "F", 7, "G"); } @Test @SuppressWarnings({ "boxing" }) public void testGetWithOneInternalNode() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(2, "B"); btree.insert(4, "D"); btree.insert(3, "C"); btree.insert(6, "F"); btree.insert(5, "E"); assertEquals("B", btree.get(2)); assertEquals("C", btree.get(3)); assertEquals("E", btree.get(5)); assertEquals("F", btree.get(6)); assertNull(btree.get(10)); assertNull(btree.get(1)); } @Test @SuppressWarnings({ "boxing" }) public void testContainsWithOneInternalNode() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(2, "B"); btree.insert(4, "D"); btree.insert(3, "C"); btree.insert(6, "F"); btree.insert(5, "E"); assertTrue(btree.contains(2)); assertTrue(btree.contains(3)); assertTrue(btree.contains(5)); assertTrue(btree.contains(6)); assertFalse(btree.contains(10)); assertFalse(btree.contains(1)); } @Test @SuppressWarnings({ "boxing" }) public void testInsertionOnRightLeafNodeWithSplit() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(2, "B"); btree.insert(4, "D"); btree.insert(3, "C"); btree.insert(6, "F"); btree.insert(5, "E"); btree.insert(7, "G"); btree.insert(9, "I"); assertInternalNode(btree.getRoot(), 2, 4, 6); InternalNode<Integer, String> internalNode = (InternalNode<Integer, String>) btree.getRoot(); assertLeafNodeContains(internalNode.getChild(0), 2, "B", 3, "C"); assertLeafNodeContains(internalNode.getChild(1), 4, "D", 5, "E"); assertLeafNodeContains(internalNode.getChild(2), 6, "F", 7, "G", 9, "I"); } @Test @SuppressWarnings({ "boxing" }) public void testInsertionOnLeftLeafNodeWithSplit() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(2, "B"); btree.insert(3, "C"); btree.insert(6, "F"); btree.insert(7, "G"); btree.insert(9, "I"); btree.insert(1, "A"); btree.insert(5, "E"); btree.insert(4, "D"); assertInternalNode(btree.getRoot(), 1, 3, 6); InternalNode<Integer, String> internalNode = (InternalNode<Integer, String>) btree.getRoot(); assertLeafNodeContains(internalNode.getChild(0), 1, "A", 2, "B"); assertLeafNodeContains(internalNode.getChild(1), 3, "C", 4, "D", 5, "E"); assertLeafNodeContains(internalNode.getChild(2), 6, "F", 7, "G", 9, "I"); } @Test @SuppressWarnings({ "boxing" }) public void testInsertionOnLeafNodeWithLeafAndParentFull() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(1, "A"); btree.insert(2, "B"); btree.insert(8, "H"); btree.insert(9, "I"); btree.insert(14, "N"); btree.insert(15, "O"); btree.insert(16, "P"); btree.insert(5, "E"); btree.insert(7, "G"); btree.insert(6, "F"); btree.insert(3, "C"); btree.insert(4, "D"); btree.insert(10, "J"); btree.insert(11, "K"); btree.insert(12, "L"); btree.insert(17, "Q"); btree.insert(18, "R"); assertInternalNode(btree.getRoot(), 1, 10); InternalNode<Integer, String> root = (InternalNode<Integer, String>) btree.getRoot(); assertInternalNode(root.getChild(0), 1, 5, 8); InternalNode<Integer, String> internalNode = (InternalNode<Integer, String>) root.getChild(0); assertLeafNodeContains(internalNode.getChild(0), 1, "A", 2, "B", 3, "C", 4, "D"); assertLeafNodeContains(internalNode.getChild(1), 5, "E", 6, "F", 7, "G"); assertLeafNodeContains(internalNode.getChild(2), 8, "H", 9, "I"); assertInternalNode(root.getChild(1), 10, 14, 16); internalNode = (InternalNode<Integer, String>) root.getChild(1); assertLeafNodeContains(internalNode.getChild(0), 10, "J", 11, "K", 12, "L"); assertLeafNodeContains(internalNode.getChild(1), 14, "N", 15, "O"); assertLeafNodeContains(internalNode.getChild(2), 16, "P", 17, "Q", 18, "R"); } @Test @SuppressWarnings({ "boxing" }) public void testInsertWith3LevelDepth() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 3); btree.insert(1, "A"); btree.insert(2, "B"); btree.insert(8, "H"); btree.insert(9, "I"); btree.insert(14, "N"); btree.insert(15, "O"); btree.insert(16, "P"); btree.insert(5, "E"); btree.insert(7, "G"); btree.insert(6, "F"); btree.insert(3, "C"); btree.insert(4, "D"); btree.insert(10, "J"); btree.insert(11, "K"); btree.insert(12, "L"); btree.insert(17, "Q"); btree.insert(18, "R"); btree.insert(13, "M"); assertInternalNode(btree.getRoot(), 1, 8, 14); InternalNode<Integer, String> root = (InternalNode<Integer, String>) btree.getRoot(); InternalNode<Integer, String> internalNodeDepth1 = (InternalNode<Integer, String>) root.getChild(0); assertInternalNode(internalNodeDepth1, 1, 5); InternalNode<Integer, String> internalNodeDepth2 = (InternalNode<Integer, String>) internalNodeDepth1.getChild(0); assertInternalNode(internalNodeDepth2, 1, 2, 3); assertLeafNodeContains(internalNodeDepth2.getChild(0), 1, "A"); assertLeafNodeContains(internalNodeDepth2.getChild(1), 2, "B"); assertLeafNodeContains(internalNodeDepth2.getChild(2), 3, "C", 4, "D"); internalNodeDepth2 = (InternalNode<Integer, String>) internalNodeDepth1.getChild(1); assertInternalNode(internalNodeDepth2, 5, 6); assertLeafNodeContains(internalNodeDepth2.getChild(0), 5, "E"); assertLeafNodeContains(internalNodeDepth2.getChild(1), 6, "F", 7, "G"); internalNodeDepth1 = (InternalNode<Integer, String>) root.getChild(1); assertInternalNode(internalNodeDepth1, 8, 10); internalNodeDepth2 = (InternalNode<Integer, String>) internalNodeDepth1.getChild(0); assertInternalNode(internalNodeDepth2, 8, 9); assertLeafNodeContains(internalNodeDepth2.getChild(0), 8, "H"); assertLeafNodeContains(internalNodeDepth2.getChild(1), 9, "I"); internalNodeDepth2 = (InternalNode<Integer, String>) internalNodeDepth1.getChild(1); assertInternalNode(internalNodeDepth2, 10, 11, 12); assertLeafNodeContains(internalNodeDepth2.getChild(0), 10, "J"); assertLeafNodeContains(internalNodeDepth2.getChild(1), 11, "K"); assertLeafNodeContains(internalNodeDepth2.getChild(2), 12, "L", 13, "M"); internalNodeDepth1 = (InternalNode<Integer, String>) root.getChild(2); assertInternalNode(internalNodeDepth1, 14, 16); internalNodeDepth2 = (InternalNode<Integer, String>) internalNodeDepth1.getChild(0); assertInternalNode(internalNodeDepth2, 14, 15); assertLeafNodeContains(internalNodeDepth2.getChild(0), 14, "N"); assertLeafNodeContains(internalNodeDepth2.getChild(1), 15, "O"); internalNodeDepth2 = (InternalNode<Integer, String>) internalNodeDepth1.getChild(1); assertInternalNode(internalNodeDepth2, 16, 17); assertLeafNodeContains(internalNodeDepth2.getChild(0), 16, "P"); assertLeafNodeContains(internalNodeDepth2.getChild(1), 17, "Q", 18, "R"); } @Test @SuppressWarnings({ "boxing" }) public void testIteratorWith3LevelDepthAndFullScan() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 3); btree.insert(1, "A"); btree.insert(2, "B"); btree.insert(8, "H"); btree.insert(9, "I"); btree.insert(14, "N"); btree.insert(15, "O"); btree.insert(16, "P"); btree.insert(5, "E"); btree.insert(7, "G"); btree.insert(6, "F"); btree.insert(3, "C"); btree.insert(4, "D"); btree.insert(10, "J"); btree.insert(11, "K"); btree.insert(12, "L"); btree.insert(17, "Q"); btree.insert(18, "R"); btree.insert(13, "M"); KeyValueIterator<Integer, String> iterator = btree.iterator(0, 100); assertNextContains(iterator, 1, "A"); assertNextContains(iterator, 2, "B"); assertNextContains(iterator, 3, "C"); assertNextContains(iterator, 4, "D"); assertNextContains(iterator, 5, "E"); assertNextContains(iterator, 6, "F"); assertNextContains(iterator, 7, "G"); assertNextContains(iterator, 8, "H"); assertNextContains(iterator, 9, "I"); assertNextContains(iterator, 10, "J"); assertNextContains(iterator, 11, "K"); assertNextContains(iterator, 12, "L"); assertNextContains(iterator, 13, "M"); assertNextContains(iterator, 14, "N"); assertNextContains(iterator, 15, "O"); assertNextContains(iterator, 16, "P"); assertNextContains(iterator, 17, "Q"); assertNextContains(iterator, 18, "R"); assertFalse(iterator.next()); } @Test @SuppressWarnings({ "boxing" }) public void testIteratorWith3LevelDepthAndPartialScan() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 3); btree.insert(1, "A"); btree.insert(2, "B"); btree.insert(8, "H"); btree.insert(9, "I"); btree.insert(14, "N"); btree.insert(15, "O"); btree.insert(16, "P"); btree.insert(5, "E"); btree.insert(7, "G"); btree.insert(6, "F"); btree.insert(3, "C"); btree.insert(4, "D"); btree.insert(10, "J"); btree.insert(11, "K"); btree.insert(12, "L"); btree.insert(17, "Q"); btree.insert(18, "R"); btree.insert(13, "M"); KeyValueIterator<Integer, String> iterator = btree.iterator(13, 14); assertNextContains(iterator, 13, "M"); assertNextContains(iterator, 14, "N"); assertFalse(iterator.next()); } @Test @SuppressWarnings({ "boxing" }) public void testGetWith3LevelDepth() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 3); btree.insert(1, "A"); btree.insert(2, "B"); btree.insert(8, "H"); btree.insert(9, "I"); btree.insert(14, "N"); btree.insert(15, "O"); btree.insert(16, "P"); btree.insert(5, "E"); btree.insert(7, "G"); btree.insert(6, "F"); btree.insert(3, "C"); btree.insert(4, "D"); btree.insert(10, "J"); btree.insert(11, "K"); btree.insert(12, "L"); btree.insert(17, "Q"); btree.insert(18, "R"); btree.insert(13, "M"); assertEquals("M", btree.get(13)); assertEquals("E", btree.get(5)); assertNull(btree.get(100)); } @Test @SuppressWarnings({ "boxing" }) public void testContainsWith3LevelDepth() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 3); btree.insert(1, "A"); btree.insert(2, "B"); btree.insert(8, "H"); btree.insert(9, "I"); btree.insert(14, "N"); btree.insert(15, "O"); btree.insert(16, "P"); btree.insert(5, "E"); btree.insert(7, "G"); btree.insert(6, "F"); btree.insert(3, "C"); btree.insert(4, "D"); btree.insert(10, "J"); btree.insert(11, "K"); btree.insert(12, "L"); btree.insert(17, "Q"); btree.insert(18, "R"); btree.insert(13, "M"); assertTrue(btree.contains(1)); assertTrue(btree.contains(18)); assertFalse(btree.contains(19)); assertFalse(btree.contains(21)); } @Test @SuppressWarnings({ "boxing" }) public void testInsertionOnLeafNodeWithLeafFullAndParentNot() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(1, "A"); btree.insert(2, "B"); btree.insert(13, "M"); btree.insert(14, "N"); btree.insert(20, "T"); btree.insert(22, "V"); btree.insert(23, "W"); btree.insert(6, "F"); btree.insert(8, "H"); btree.insert(7, "G"); btree.insert(3, "C"); btree.insert(4, "D"); btree.insert(15, "O"); btree.insert(17, "Q"); btree.insert(18, "R"); btree.insert(24, "X"); btree.insert(25, "Y"); btree.insert(5, "E"); btree.insert(9, "I"); btree.insert(10, "J"); btree.insert(11, "K"); btree.insert(12, "L"); assertInternalNode(btree.getRoot(), 1, 8, 15); InternalNode<Integer, String> root = (InternalNode<Integer, String>) btree.getRoot(); assertInternalNode(root.getChild(0), 1, 3, 6); InternalNode<Integer, String> internalNode = (InternalNode<Integer, String>) root.getChild(0); assertLeafNodeContains(internalNode.getChild(0), 1, "A", 2, "B"); assertLeafNodeContains(internalNode.getChild(1), 3, "C", 4, "D", 5, "E"); assertLeafNodeContains(internalNode.getChild(2), 6, "F", 7, "G"); assertInternalNode(root.getChild(1), 8, 10, 13); internalNode = (InternalNode<Integer, String>) root.getChild(1); assertLeafNodeContains(internalNode.getChild(0), 8, "H", 9, "I"); assertLeafNodeContains(internalNode.getChild(1), 10, "J", 11, "K", 12, "L"); assertLeafNodeContains(internalNode.getChild(2), 13, "M", 14, "N"); assertInternalNode(root.getChild(2), 15, 20, 23); internalNode = (InternalNode<Integer, String>) root.getChild(2); assertLeafNodeContains(internalNode.getChild(0), 15, "O", 17, "Q", 18, "R"); assertLeafNodeContains(internalNode.getChild(1), 20, "T", 22, "V"); assertLeafNodeContains(internalNode.getChild(2), 23, "W", 24, "X", 25, "Y"); } @Test @SuppressWarnings({ "boxing" }) public void testInsertWithInternalNodeSplitWithParentNotFull() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(1, "A"); btree.insert(2, "B"); btree.insert(13, "M"); btree.insert(14, "N"); btree.insert(20, "T"); btree.insert(22, "V"); btree.insert(23, "W"); btree.insert(6, "F"); btree.insert(8, "H"); btree.insert(7, "G"); btree.insert(3, "C"); btree.insert(4, "D"); btree.insert(15, "O"); btree.insert(17, "Q"); btree.insert(18, "R"); btree.insert(24, "X"); btree.insert(25, "Y"); btree.insert(18, "S"); assertInternalNode(btree.getRoot(), 1, 15); InternalNode<Integer, String> root = (InternalNode<Integer, String>) btree.getRoot(); assertInternalNode(root.getChild(0), 1, 6, 13); InternalNode<Integer, String> internalNode = (InternalNode<Integer, String>) root.getChild(0); assertLeafNodeContains(internalNode.getChild(0), 1, "A", 2, "B", 3, "C", 4, "D"); assertLeafNodeContains(internalNode.getChild(1), 6, "F", 7, "G", 8, "H"); assertLeafNodeContains(internalNode.getChild(2), 13, "M", 14, "N"); assertInternalNode(root.getChild(1), 15, 20, 23); internalNode = (InternalNode<Integer, String>) root.getChild(1); assertLeafNodeContains(internalNode.getChild(0), 15, "O", 17, "Q", 18, "R", 18, "S"); assertLeafNodeContains(internalNode.getChild(1), 20, "T", 22, "V"); assertLeafNodeContains(internalNode.getChild(2), 23, "W", 24, "X", 25, "Y"); btree.insert(26, "Z"); btree.insert(27, "AA"); btree.insert(28, "BB"); btree.insert(29, "CC"); btree.insert(30, "DD"); btree.insert(31, "EE"); assertInternalNode(btree.getRoot(), 1, 15, 25); root = (InternalNode<Integer, String>) btree.getRoot(); assertInternalNode(root.getChild(0), 1, 6, 13); internalNode = (InternalNode<Integer, String>) root.getChild(0); assertLeafNodeContains(internalNode.getChild(0), 1, "A", 2, "B", 3, "C", 4, "D"); assertLeafNodeContains(internalNode.getChild(1), 6, "F", 7, "G", 8, "H"); assertLeafNodeContains(internalNode.getChild(2), 13, "M", 14, "N"); assertInternalNode(root.getChild(1), 15, 20, 23); internalNode = (InternalNode<Integer, String>) root.getChild(1); assertLeafNodeContains(internalNode.getChild(0), 15, "O", 17, "Q", 18, "R", 18, "S"); assertLeafNodeContains(internalNode.getChild(1), 20, "T", 22, "V"); assertLeafNodeContains(internalNode.getChild(2), 23, "W", 24, "X"); assertInternalNode(root.getChild(2), 25, 27, 29); internalNode = (InternalNode<Integer, String>) root.getChild(2); assertLeafNodeContains(internalNode.getChild(0), 25, "Y", 26, "Z"); assertLeafNodeContains(internalNode.getChild(1), 27, "AA", 28, "BB"); assertLeafNodeContains(internalNode.getChild(2), 29, "CC", 30, "DD", 31, "EE"); } @Test @SuppressWarnings({ "boxing" }) public void testDeletingKeysWhichAreWithinTheRoot() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(1, "A"); btree.insert(2, "B"); btree.insert(13, "M"); btree.insert(14, "N"); btree.insert(20, "T"); btree.insert(22, "V"); btree.insert(23, "W"); btree.insert(6, "F"); btree.insert(8, "H"); btree.insert(7, "G"); btree.insert(3, "C"); btree.insert(4, "D"); btree.insert(15, "O"); btree.insert(17, "Q"); btree.insert(18, "R"); btree.insert(24, "X"); btree.insert(25, "Y"); btree.insert(18, "S"); assertInternalNode(btree.getRoot(), 1, 15); InternalNode<Integer, String> root = (InternalNode<Integer, String>) btree.getRoot(); assertInternalNode(root.getChild(0), 1, 6, 13); InternalNode<Integer, String> internalNode = (InternalNode<Integer, String>) root.getChild(0); assertLeafNodeContains(internalNode.getChild(0), 1, "A", 2, "B", 3, "C", 4, "D"); assertLeafNodeContains(internalNode.getChild(1), 6, "F", 7, "G", 8, "H"); assertLeafNodeContains(internalNode.getChild(2), 13, "M", 14, "N"); assertInternalNode(root.getChild(1), 15, 20, 23); internalNode = (InternalNode<Integer, String>) root.getChild(1); assertLeafNodeContains(internalNode.getChild(0), 15, "O", 17, "Q", 18, "R", 18, "S"); assertLeafNodeContains(internalNode.getChild(1), 20, "T", 22, "V"); assertLeafNodeContains(internalNode.getChild(2), 23, "W", 24, "X", 25, "Y"); btree.delete(15); btree.delete(1); assertInternalNode(btree.getRoot(), 2, 17); root = (InternalNode<Integer, String>) btree.getRoot(); assertInternalNode(root.getChild(0), 2, 6, 13); internalNode = (InternalNode<Integer, String>) root.getChild(0); assertLeafNodeContains(internalNode.getChild(0), 2, "B", 3, "C", 4, "D"); assertLeafNodeContains(internalNode.getChild(1), 6, "F", 7, "G", 8, "H"); assertLeafNodeContains(internalNode.getChild(2), 13, "M", 14, "N"); assertInternalNode(root.getChild(1), 17, 20, 23); internalNode = (InternalNode<Integer, String>) root.getChild(1); assertLeafNodeContains(internalNode.getChild(0), 17, "Q", 18, "R", 18, "S"); assertLeafNodeContains(internalNode.getChild(1), 20, "T", 22, "V"); assertLeafNodeContains(internalNode.getChild(2), 23, "W", 24, "X", 25, "Y"); } @Test @SuppressWarnings({ "boxing" }) public void testDeletionWithInternalNodeRebalancingFromTheRightNode() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(1, "A"); btree.insert(2, "B"); btree.insert(8, "H"); btree.insert(9, "I"); btree.insert(14, "N"); btree.insert(15, "O"); btree.insert(16, "P"); btree.insert(5, "E"); btree.insert(7, "G"); btree.insert(6, "F"); btree.insert(3, "C"); btree.insert(4, "D"); btree.insert(10, "J"); btree.insert(11, "K"); btree.insert(12, "L"); btree.insert(20, "T"); btree.insert(21, "U"); btree.insert(13, "M"); btree.insert(23, "W"); btree.insert(24, "X"); btree.insert(25, "Y"); btree.insert(26, "Z"); btree.insert(27, "AA"); btree.insert(28, "BB"); btree.insert(17, "Q"); btree.insert(18, "R"); btree.insert(19, "S"); assertInternalNode(btree.getRoot(), 1, 10, 21); InternalNode<Integer, String> root = (InternalNode<Integer, String>) btree.getRoot(); assertInternalNode(root.getChild(0), 1, 5, 8); InternalNode<Integer, String> internalNode = (InternalNode<Integer, String>) root.getChild(0); assertLeafNodeContains(internalNode.getChild(0), 1, "A", 2, "B", 3, "C", 4, "D"); assertLeafNodeContains(internalNode.getChild(1), 5, "E", 6, "F", 7, "G"); assertLeafNodeContains(internalNode.getChild(2), 8, "H", 9, "I"); assertInternalNode(root.getChild(1), 10, 14, 16, 18); internalNode = (InternalNode<Integer, String>) root.getChild(1); assertLeafNodeContains(internalNode.getChild(0), 10, "J", 11, "K", 12, "L", 13, "M"); assertLeafNodeContains(internalNode.getChild(1), 14, "N", 15, "O"); assertLeafNodeContains(internalNode.getChild(2), 16, "P", 17, "Q"); assertLeafNodeContains(internalNode.getChild(3), 18, "R", 19, "S", 20, "T"); assertInternalNode(root.getChild(2), 21, 24, 26); internalNode = (InternalNode<Integer, String>) root.getChild(2); assertLeafNodeContains(internalNode.getChild(0), 21, "U", 23, "W"); assertLeafNodeContains(internalNode.getChild(1), 24, "X", 25, "Y"); assertLeafNodeContains(internalNode.getChild(2), 26, "Z", 27, "AA", 28, "BB"); btree.delete(25); btree.delete(4); btree.delete(2); btree.delete(7); btree.delete(5); assertInternalNode(btree.getRoot(), 1, 14, 21); root = (InternalNode<Integer, String>) btree.getRoot(); assertInternalNode(root.getChild(0), 1, 6, 10); internalNode = (InternalNode<Integer, String>) root.getChild(0); assertLeafNodeContains(internalNode.getChild(0), 1, "A", 3, "C"); assertLeafNodeContains(internalNode.getChild(1), 6, "F", 8, "H", 9, "I"); assertLeafNodeContains(internalNode.getChild(2), 10, "J", 11, "K", 12, "L", 13, "M"); assertInternalNode(root.getChild(1), 14, 16, 18); internalNode = (InternalNode<Integer, String>) root.getChild(1); assertLeafNodeContains(internalNode.getChild(0), 14, "N", 15, "O"); assertLeafNodeContains(internalNode.getChild(1), 16, "P", 17, "Q"); assertLeafNodeContains(internalNode.getChild(2), 18, "R", 19, "S", 20, "T"); assertInternalNode(root.getChild(2), 21, 24, 27); internalNode = (InternalNode<Integer, String>) root.getChild(2); assertLeafNodeContains(internalNode.getChild(0), 21, "U", 23, "W"); assertLeafNodeContains(internalNode.getChild(1), 24, "X", 26, "Z"); assertLeafNodeContains(internalNode.getChild(2), 27, "AA", 28, "BB"); } @Test @SuppressWarnings({ "boxing" }) public void testDeleteWithInternalNodeRebalancingFromTheLeftNode() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(1, "A"); btree.insert(2, "B"); btree.insert(8, "H"); btree.insert(9, "I"); btree.insert(14, "N"); btree.insert(15, "O"); btree.insert(16, "P"); btree.insert(5, "E"); btree.insert(7, "G"); btree.insert(6, "F"); btree.insert(3, "C"); btree.insert(4, "D"); btree.insert(10, "J"); btree.insert(11, "K"); btree.insert(12, "L"); btree.insert(20, "T"); btree.insert(21, "U"); btree.insert(13, "M"); btree.insert(23, "W"); btree.insert(24, "X"); btree.insert(25, "Y"); btree.insert(26, "Z"); btree.insert(27, "AA"); btree.insert(28, "BB"); btree.insert(17, "Q"); btree.insert(18, "R"); btree.insert(19, "S"); btree.insert(22, "V"); assertInternalNode(btree.getRoot(), 1, 10, 21); InternalNode<Integer, String> root = (InternalNode<Integer, String>) btree.getRoot(); assertInternalNode(root.getChild(0), 1, 5, 8); InternalNode<Integer, String> internalNode = (InternalNode<Integer, String>) root.getChild(0); assertLeafNodeContains(internalNode.getChild(0), 1, "A", 2, "B", 3, "C", 4, "D"); assertLeafNodeContains(internalNode.getChild(1), 5, "E", 6, "F", 7, "G"); assertLeafNodeContains(internalNode.getChild(2), 8, "H", 9, "I"); assertInternalNode(root.getChild(1), 10, 14, 16, 18); internalNode = (InternalNode<Integer, String>) root.getChild(1); assertLeafNodeContains(internalNode.getChild(0), 10, "J", 11, "K", 12, "L", 13, "M"); assertLeafNodeContains(internalNode.getChild(1), 14, "N", 15, "O"); assertLeafNodeContains(internalNode.getChild(2), 16, "P", 17, "Q"); assertLeafNodeContains(internalNode.getChild(3), 18, "R", 19, "S", 20, "T"); assertInternalNode(root.getChild(2), 21, 24, 26); internalNode = (InternalNode<Integer, String>) root.getChild(2); assertLeafNodeContains(internalNode.getChild(0), 21, "U", 22, "V", 23, "W"); assertLeafNodeContains(internalNode.getChild(1), 24, "X", 25, "Y"); assertLeafNodeContains(internalNode.getChild(2), 26, "Z", 27, "AA", 28, "BB"); btree.delete(27); btree.delete(24); btree.delete(22); assertInternalNode(btree.getRoot(), 1, 10, 18); root = (InternalNode<Integer, String>) btree.getRoot(); assertInternalNode(root.getChild(0), 1, 5, 8); internalNode = (InternalNode<Integer, String>) root.getChild(0); assertLeafNodeContains(internalNode.getChild(0), 1, "A", 2, "B", 3, "C", 4, "D"); assertLeafNodeContains(internalNode.getChild(1), 5, "E", 6, "F", 7, "G"); assertLeafNodeContains(internalNode.getChild(2), 8, "H", 9, "I"); assertInternalNode(root.getChild(1), 10, 14, 16); internalNode = (InternalNode<Integer, String>) root.getChild(1); assertLeafNodeContains(internalNode.getChild(0), 10, "J", 11, "K", 12, "L", 13, "M"); assertLeafNodeContains(internalNode.getChild(1), 14, "N", 15, "O"); assertLeafNodeContains(internalNode.getChild(2), 16, "P", 17, "Q"); assertInternalNode(root.getChild(2), 18, 21, 26); internalNode = (InternalNode<Integer, String>) root.getChild(2); assertLeafNodeContains(internalNode.getChild(0), 18, "R", 19, "S", 20, "T"); assertLeafNodeContains(internalNode.getChild(1), 21, "U", 23, "W", 25, "Y"); assertLeafNodeContains(internalNode.getChild(2), 26, "Z", 28, "BB"); } @Test @SuppressWarnings({ "boxing" }) public void testDeletionOfKeyFromLeafNodeWithRedistributionOnRightNode() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(1, "A"); btree.insert(2, "B"); btree.insert(4, "D"); btree.insert(5, "E"); btree.insert(7, "G"); btree.insert(8, "H"); btree.insert(9, "I"); btree.insert(3, "C"); btree.insert(6, "F"); btree.insert(10, "J"); btree.delete(1); btree.delete(2); assertInternalNode(btree.getRoot(), 3, 5, 7); InternalNode<Integer, String> internalNode = (InternalNode<Integer, String>) btree.getRoot(); assertLeafNodeContains(internalNode.getChild(0), 3, "C", 4, "D"); assertLeafNodeContains(internalNode.getChild(1), 5, "E", 6, "F"); assertLeafNodeContains(internalNode.getChild(2), 7, "G", 8, "H", 9, "I", 10, "J"); } @Test @SuppressWarnings({ "boxing" }) public void testDeletionOfKeyFromLeafNodeWithFirstKeyDeletedAndRedistribution() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(1, "A"); btree.insert(2, "B"); btree.insert(4, "D"); btree.insert(5, "E"); btree.insert(7, "G"); btree.insert(8, "H"); btree.insert(9, "I"); btree.insert(3, "C"); btree.insert(6, "F"); btree.insert(10, "J"); btree.delete(4); btree.delete(5); assertInternalNode(btree.getRoot(), 1, 6, 8); InternalNode<Integer, String> internalNode = (InternalNode<Integer, String>) btree.getRoot(); assertLeafNodeContains(internalNode.getChild(0), 1, "A", 2, "B", 3, "C"); assertLeafNodeContains(internalNode.getChild(1), 6, "F", 7, "G"); assertLeafNodeContains(internalNode.getChild(2), 8, "H", 9, "I", 10, "J"); } @Test @SuppressWarnings({ "boxing" }) public void testDeletionOfKeyFromLeafNodeWithRedistributionOnLeftNode() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(1, "A"); btree.insert(2, "B"); btree.insert(4, "D"); btree.insert(5, "E"); btree.insert(7, "G"); btree.insert(8, "H"); btree.insert(9, "I"); btree.insert(3, "C"); btree.insert(6, "F"); btree.insert(10, "J"); btree.delete(8); btree.delete(9); assertInternalNode(btree.getRoot(), 1, 4, 7); InternalNode<Integer, String> internalNode = (InternalNode<Integer, String>) btree.getRoot(); assertLeafNodeContains(internalNode.getChild(0), 1, "A", 2, "B", 3, "C"); assertLeafNodeContains(internalNode.getChild(1), 4, "D", 5, "E", 6, "F"); assertLeafNodeContains(internalNode.getChild(2), 7, "G", 10, "J"); } @Test @SuppressWarnings({ "boxing" }) public void testDeletionOfKeyFromLeafNodeWithMergeOnTheRight() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(1, "A"); btree.insert(2, "B"); btree.insert(4, "D"); btree.insert(5, "E"); btree.insert(7, "G"); btree.insert(8, "H"); btree.insert(9, "I"); btree.insert(3, "C"); btree.insert(6, "F"); btree.delete(3); btree.delete(8); btree.delete(5); btree.delete(1); assertInternalNode(btree.getRoot(), 2, 7); InternalNode<Integer, String> internalNode = (InternalNode<Integer, String>) btree.getRoot(); assertLeafNodeContains(internalNode.getChild(0), 2, "B", 4, "D", 6, "F"); assertLeafNodeContains(internalNode.getChild(1), 7, "G", 9, "I"); } @Test @SuppressWarnings({ "boxing" }) public void testDeletionOfKeyFromLeafNodeWithMergeOnTheLeft() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(1, "A"); btree.insert(2, "B"); btree.insert(4, "D"); btree.insert(5, "E"); btree.insert(7, "G"); btree.insert(8, "H"); btree.insert(9, "I"); btree.insert(3, "C"); btree.insert(6, "F"); btree.delete(3); btree.delete(8); btree.delete(5); btree.delete(4); assertInternalNode(btree.getRoot(), 1, 6); InternalNode<Integer, String> internalNode = (InternalNode<Integer, String>) btree.getRoot(); assertLeafNodeContains(internalNode.getChild(0), 1, "A", 2, "B"); assertLeafNodeContains(internalNode.getChild(1), 6, "F", 7, "G", 9, "I"); } @Test @SuppressWarnings({ "boxing" }) public void testDeletionOfKeyFromLeafNodeWithMergeAndNoRightNode() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(1, "A"); btree.insert(2, "B"); btree.insert(4, "D"); btree.insert(5, "E"); btree.insert(7, "G"); btree.insert(8, "H"); btree.insert(9, "I"); btree.insert(3, "C"); btree.insert(6, "F"); btree.delete(4); btree.delete(8); btree.delete(5); btree.delete(7); assertInternalNode(btree.getRoot(), 1, 3); InternalNode<Integer, String> internalNode = (InternalNode<Integer, String>) btree.getRoot(); assertLeafNodeContains(internalNode.getChild(0), 1, "A", 2, "B"); assertLeafNodeContains(internalNode.getChild(1), 3, "C", 6, "F", 9, "I"); } @Test @SuppressWarnings({ "boxing" }) public void testDeletionWithLeafNodeMergeAndInternalNodeMerge() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(1, "A"); btree.insert(2, "B"); btree.insert(8, "H"); btree.insert(9, "I"); btree.insert(13, "M"); btree.insert(14, "N"); btree.insert(15, "O"); btree.insert(5, "E"); btree.insert(7, "G"); btree.insert(6, "F"); btree.insert(3, "C"); btree.insert(4, "D"); btree.insert(10, "J"); btree.insert(11, "K"); btree.insert(12, "L"); btree.insert(16, "P"); btree.insert(17, "Q"); btree.delete(12); btree.delete(5); btree.delete(10); assertInternalNode(btree.getRoot(), 1, 6, 8, 11, 15); InternalNode<Integer, String> root = (InternalNode<Integer, String>) btree.getRoot(); assertLeafNodeContains(root.getChild(0), 1, "A", 2, "B", 3, "C", 4, "D"); assertLeafNodeContains(root.getChild(1), 6, "F", 7, "G"); assertLeafNodeContains(root.getChild(2), 8, "H", 9, "I"); assertLeafNodeContains(root.getChild(3), 11, "K", 13, "M", 14, "N"); assertLeafNodeContains(root.getChild(4), 15, "O", 16, "P", 17, "Q"); } @Test @SuppressWarnings({ "boxing" }) public void testAccept() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(1, "A"); btree.insert(2, "B"); btree.insert(8, "H"); btree.insert(9, "I"); btree.insert(13, "M"); btree.insert(14, "N"); btree.insert(15, "O"); btree.insert(5, "E"); btree.insert(7, "G"); btree.insert(6, "F"); btree.insert(3, "C"); btree.insert(4, "D"); btree.insert(10, "J"); btree.insert(11, "K"); btree.insert(12, "L"); btree.insert(16, "P"); btree.insert(17, "Q"); KeyCollector collector = new KeyCollector(); btree.accept(collector); AssertCollections.assertListContains(collector.getKeys(), 1, 1, 1, 1, 2, 3, 4, 5, 5, 6, 7, 8, 8, 9, 10, 10, 10, 11, 12, 13, 13, 14, 15, 15, 16, 17); } @Test @SuppressWarnings({ "boxing" }) public void testAcceptWithSkipSubTree() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(1, "A"); btree.insert(2, "B"); btree.insert(8, "H"); btree.insert(9, "I"); btree.insert(13, "M"); btree.insert(14, "N"); btree.insert(15, "O"); btree.insert(5, "E"); btree.insert(7, "G"); btree.insert(6, "F"); btree.insert(3, "C"); btree.insert(4, "D"); btree.insert(10, "J"); btree.insert(11, "K"); btree.insert(12, "L"); btree.insert(16, "P"); btree.insert(17, "Q"); KeyCollector collector = new KeyCollector() { @Override public NodeVisitResult preVisitNode(Integer key, Node<Integer, String> node) throws IOException { NodeVisitResult result = super.preVisitNode(key, node); if (node.getType() == Node.LEAF_NODE) { return NodeVisitResult.SKIP_SUBTREE; } return result; } }; btree.accept(collector); AssertCollections.assertListContains(collector.getKeys(), 1, 1, 1, 5, 8, 10, 10, 13, 15); } @Test @SuppressWarnings({ "boxing" }) public void testAcceptWithSkipSiblings() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(1, "A"); btree.insert(2, "B"); btree.insert(8, "H"); btree.insert(9, "I"); btree.insert(13, "M"); btree.insert(14, "N"); btree.insert(15, "O"); btree.insert(5, "E"); btree.insert(7, "G"); btree.insert(6, "F"); btree.insert(3, "C"); btree.insert(4, "D"); btree.insert(10, "J"); btree.insert(11, "K"); btree.insert(12, "L"); btree.insert(16, "P"); btree.insert(17, "Q"); KeyCollector collector = new KeyCollector() { @Override public NodeVisitResult preVisitNode(Integer key, Node<Integer, String> node) throws IOException { NodeVisitResult result = super.preVisitNode(key, node); if (node.getType() == Node.LEAF_NODE) { return NodeVisitResult.SKIP_SIBLINGS; } return result; } }; btree.accept(collector); AssertCollections.assertListContains(collector.getKeys(), 1, 1, 1, 10, 10); } @Test @SuppressWarnings({ "boxing" }) public void testAcceptWithSkipSiblingsOnRecords() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(1, "A"); btree.insert(2, "B"); btree.insert(8, "H"); btree.insert(9, "I"); btree.insert(13, "M"); btree.insert(14, "N"); btree.insert(15, "O"); btree.insert(5, "E"); btree.insert(7, "G"); btree.insert(6, "F"); btree.insert(3, "C"); btree.insert(4, "D"); btree.insert(10, "J"); btree.insert(11, "K"); btree.insert(12, "L"); btree.insert(16, "P"); btree.insert(17, "Q"); KeyCollector collector = new KeyCollector() { @Override public NodeVisitResult visitRecord(Integer key, ValueWrapper<String> pointer) { getKeys().add(key); return NodeVisitResult.SKIP_SIBLINGS; } }; btree.accept(collector); AssertCollections.assertListContains(collector.getKeys(), 1, 1, 1, 1, 5, 5, 8, 8, 10, 10, 10, 13, 13, 15, 15); } @Test @SuppressWarnings({ "boxing" }) public void testAcceptWithTerminate() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(1, "A"); btree.insert(2, "B"); btree.insert(8, "H"); btree.insert(9, "I"); btree.insert(13, "M"); btree.insert(14, "N"); btree.insert(15, "O"); btree.insert(5, "E"); btree.insert(7, "G"); btree.insert(6, "F"); btree.insert(3, "C"); btree.insert(4, "D"); btree.insert(10, "J"); btree.insert(11, "K"); btree.insert(12, "L"); btree.insert(16, "P"); btree.insert(17, "Q"); KeyCollector collector = new KeyCollector() { @Override public NodeVisitResult preVisitNode(Integer key, Node<Integer, String> node) throws IOException { NodeVisitResult result = super.preVisitNode(key, node); if (node.getType() == Node.LEAF_NODE) { return NodeVisitResult.TERMINATE; } return result; } }; btree.accept(collector); AssertCollections.assertListContains(collector.getKeys(), 1, 1, 1); } @Test @SuppressWarnings({ "boxing" }) public void testAcceptWithNull() throws IOException { BTree<Integer, String> btree = new BTree<>(this.manager, 5); btree.insert(1, "A"); btree.insert(2, "B"); btree.insert(8, "H"); btree.insert(9, "I"); btree.insert(13, "M"); btree.insert(14, "N"); btree.insert(15, "O"); btree.insert(5, "E"); btree.insert(7, "G"); btree.insert(6, "F"); btree.insert(3, "C"); btree.insert(4, "D"); btree.insert(10, "J"); btree.insert(11, "K"); btree.insert(12, "L"); btree.insert(16, "P"); btree.insert(17, "Q"); btree.accept(null); } /** * Asserts that the key and the value of the next record returned by the iterator are equals to * the specified ones. * * @param iterator the iterator to check * @param key the expected key * @param value the expected value * @throws IOException if an I/O problem occurs */ private static void assertNextContains(KeyValueIterator<Integer, String> iterator, Integer key, String value) throws IOException { assertTrue(iterator.next()); assertEquals(key, iterator.getKey()); assertEquals(value, iterator.getValue()); } /** * The visitor used during the tests. * * @author Benjamin * */ public class KeyCollector implements NodeVisitor<Integer, String> { /** * The collected keys. */ private final List<Integer> keys = new ArrayList<>(); /** * Returns the collected keys. * * @return the collected keys. */ public List<Integer> getKeys() { return this.keys; } /** * {@inheritDoc} */ @Override public NodeVisitResult preVisitNode(Integer key, Node<Integer, String> node) throws IOException { this.keys.add(key); return NodeVisitResult.CONTINUE; } /** * {@inheritDoc} */ @Override public NodeVisitResult postVisitNode(Integer key, Node<Integer, String> node) { return NodeVisitResult.CONTINUE; } /** * {@inheritDoc} */ @Override public NodeVisitResult visitRecord(Integer key, ValueWrapper<String> pointer) { this.keys.add(key); return NodeVisitResult.CONTINUE; } } }