package org.jabref.model; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.function.Consumer; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.verify; @RunWith(MockitoJUnitRunner.class) public class TreeNodeTest { @Mock Consumer<TreeNodeTestData.TreeNodeMock> subscriber; @Test(expected = UnsupportedOperationException.class) public void constructorChecksThatClassImplementsCorrectInterface() { new WrongTreeNodeImplementation(); } @Test public void constructorExceptsCorrectImplementation() { TreeNodeTestData.TreeNodeMock treeNode = new TreeNodeTestData.TreeNodeMock(); assertNotNull(treeNode); } @Test public void newTreeNodeHasNoParentOrChildren() { TreeNodeTestData.TreeNodeMock treeNode = new TreeNodeTestData.TreeNodeMock(); assertEquals(Optional.empty(), treeNode.getParent()); assertEquals(Collections.emptyList(), treeNode.getChildren()); assertNotNull(treeNode); } @Test public void getIndexedPathFromRootReturnsEmptyListForRoot() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); assertEquals(Collections.emptyList(), root.getIndexedPathFromRoot()); } @Test public void getIndexedPathFromRootSimplePath() { assertEquals(Arrays.asList(1, 0), TreeNodeTestData.getNodeInSimpleTree().getIndexedPathFromRoot()); } @Test public void getIndexedPathFromRootComplexPath() { assertEquals(Arrays.asList(2, 1, 0), TreeNodeTestData.getNodeInComplexTree().getIndexedPathFromRoot()); } @Test public void getDescendantSimplePath() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeInSimpleTree(root); assertEquals(node, root.getDescendant(Arrays.asList(1, 0)).get()); } @Test public void getDescendantComplexPath() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeInComplexTree(root); assertEquals(node, root.getDescendant(Arrays.asList(2, 1, 0)).get()); } @Test public void getDescendantNonExistentReturnsEmpty() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.getNodeInComplexTree(root); assertEquals(Optional.empty(), root.getDescendant(Arrays.asList(1, 100, 0))); } @Test(expected = UnsupportedOperationException.class) public void getPositionInParentForRootThrowsException() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); root.getPositionInParent(); } @Test public void getPositionInParentSimpleTree() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeAsChild(root); assertEquals(2, node.getPositionInParent()); } @Test public void getIndexOfNonExistentChildReturnsEmpty() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); assertEquals(Optional.empty(), root.getIndexOfChild(new TreeNodeTestData.TreeNodeMock())); } @Test public void getIndexOfChild() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeAsChild(root); assertEquals((Integer)2, root.getIndexOfChild(node).get()); } @Test public void getLevelOfRoot() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); assertEquals(0, root.getLevel()); } @Test public void getLevelInSimpleTree() { assertEquals(2, TreeNodeTestData.getNodeInSimpleTree().getLevel()); } @Test public void getLevelInComplexTree() { assertEquals(3, TreeNodeTestData.getNodeInComplexTree().getLevel()); } @Test public void getChildCountInSimpleTree() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.getNodeInSimpleTree(root); assertEquals(2, root.getNumberOfChildren()); } @Test public void getChildCountInComplexTree() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.getNodeInComplexTree(root); assertEquals(4, root.getNumberOfChildren()); } @Test public void moveToAddsAsLastChildInSimpleTree() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeInSimpleTree(root); node.moveTo(root); assertEquals((Integer)2, root.getIndexOfChild(node).get()); } @Test public void moveToAddsAsLastChildInComplexTree() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeInComplexTree(root); node.moveTo(root); assertEquals((Integer)4, root.getIndexOfChild(node).get()); } @Test public void moveToChangesParent() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeInSimpleTree(root); node.moveTo(root); assertEquals(root, node.getParent().get()); } @Test public void moveToInSameLevelAddsAtEnd() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock child1 = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock child2 = new TreeNodeTestData.TreeNodeMock(); root.addChild(child1); root.addChild(child2); child1.moveTo(root); assertEquals(Arrays.asList(child2, child1), root.getChildren()); } @Test public void getPathFromRootInSimpleTree() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeInSimpleTree(root); List<TreeNodeTestData.TreeNodeMock> path = node.getPathFromRoot(); assertEquals(3, path.size()); assertEquals(root, path.get(0)); assertEquals(node, path.get(2)); } @Test public void getPathFromRootInComplexTree() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeInComplexTree(root); List<TreeNodeTestData.TreeNodeMock> path = node.getPathFromRoot(); assertEquals(4, path.size()); assertEquals(root, path.get(0)); assertEquals(node, path.get(3)); } @Test public void getPreviousSiblingReturnsCorrect() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); root.addChild(new TreeNodeTestData.TreeNodeMock()); TreeNodeTestData.TreeNodeMock previous = new TreeNodeTestData.TreeNodeMock(); root.addChild(previous); TreeNodeTestData.TreeNodeMock node = new TreeNodeTestData.TreeNodeMock(); root.addChild(node); root.addChild(new TreeNodeTestData.TreeNodeMock()); assertEquals(previous, node.getPreviousSibling().get()); } @Test public void getPreviousSiblingForRootReturnsEmpty() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); assertEquals(Optional.empty(), root.getPreviousSibling()); } @Test public void getPreviousSiblingForNonexistentReturnsEmpty() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = new TreeNodeTestData.TreeNodeMock(); root.addChild(node); assertEquals(Optional.empty(), node.getPreviousSibling()); } @Test public void getNextSiblingReturnsCorrect() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); root.addChild(new TreeNodeTestData.TreeNodeMock()); TreeNodeTestData.TreeNodeMock node = new TreeNodeTestData.TreeNodeMock(); root.addChild(node); TreeNodeTestData.TreeNodeMock next = new TreeNodeTestData.TreeNodeMock(); root.addChild(next); root.addChild(new TreeNodeTestData.TreeNodeMock()); assertEquals(next, node.getNextSibling().get()); } @Test public void getNextSiblingForRootReturnsEmpty() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); assertEquals(Optional.empty(), root.getNextSibling()); } @Test public void getNextSiblingForNonexistentReturnsEmpty() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = new TreeNodeTestData.TreeNodeMock(); root.addChild(node); assertEquals(Optional.empty(), node.getPreviousSibling()); } @Test public void getParentReturnsCorrect() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeAsChild(root); assertEquals(root, node.getParent().get()); } @Test public void getParentForRootReturnsEmpty() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); assertEquals(Optional.empty(), root.getParent()); } @Test public void getChildAtReturnsCorrect() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeAsChild(root); assertEquals(node, root.getChildAt(2).get()); } @Test public void getChildAtInvalidIndexReturnsEmpty() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); root.addChild(new TreeNodeTestData.TreeNodeMock()); root.addChild(new TreeNodeTestData.TreeNodeMock()); assertEquals(Optional.empty(), root.getChildAt(10)); } @Test public void getRootReturnsTrueForRoot() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); assertTrue(root.isRoot()); } @Test public void getRootReturnsFalseForChild() { assertFalse(TreeNodeTestData.getNodeInSimpleTree().isRoot()); } @Test public void nodeIsAncestorOfItself() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); assertTrue(root.isAncestorOf(root)); } @Test public void isAncestorOfInSimpleTree() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeInSimpleTree(root); assertTrue(root.isAncestorOf(node)); } @Test public void isAncestorOfInComplexTree() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeInComplexTree(root); assertTrue(root.isAncestorOf(node)); } @Test public void getRootOfSingleNode() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); assertEquals(root, root.getRoot()); } @Test public void getRootInSimpleTree() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeInSimpleTree(root); assertEquals(root, node.getRoot()); } @Test public void getRootInComplexTree() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeInComplexTree(root); assertEquals(root, node.getRoot()); } @Test public void isLeafIsCorrectForRootWithoutChildren() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); assertTrue(root.isLeaf()); } @Test public void removeFromParentSetsParentToEmpty() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeAsChild(root); node.removeFromParent(); assertEquals(Optional.empty(), node.getParent()); } @Test public void removeFromParentRemovesNodeFromChildrenCollection() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeAsChild(root); node.removeFromParent(); assertFalse(root.getChildren().contains(node)); } @Test public void removeAllChildrenSetsParentOfChildToEmpty() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeAsChild(root); root.removeAllChildren(); assertEquals(Optional.empty(), node.getParent()); } @Test public void removeAllChildrenRemovesAllNodesFromChildrenCollection() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.getNodeAsChild(root); root.removeAllChildren(); assertEquals(Collections.emptyList(), root.getChildren()); } @Test public void getFirstChildAtReturnsCorrect() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = new TreeNodeTestData.TreeNodeMock(); root.addChild(node); assertEquals(node, root.getFirstChild().get()); } @Test public void getFirstChildAtLeafReturnsEmpty() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock leaf = TreeNodeTestData.getNodeAsChild(root); assertEquals(Optional.empty(), leaf.getFirstChild()); } @Test public void isNodeDescendantInFirstLevel() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock child = TreeNodeTestData.getNodeAsChild(root); assertTrue(root.isNodeDescendant(child)); } @Test public void isNodeDescendantInComplex() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock descendant = TreeNodeTestData.getNodeInComplexTree(root); assertTrue(root.isNodeDescendant(descendant)); } @Test public void getChildrenReturnsAllChildren() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock child1 = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock child2 = new TreeNodeTestData.TreeNodeMock(); root.addChild(child1); root.addChild(child2); assertEquals(Arrays.asList(child1, child2), root.getChildren()); } @Test public void removeChildSetsParentToEmpty() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeAsChild(root); root.removeChild(node); assertEquals(Optional.empty(), node.getParent()); } @Test public void removeChildRemovesNodeFromChildrenCollection() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeAsChild(root); root.removeChild(node); assertFalse(root.getChildren().contains(node)); } @Test public void removeChildIndexSetsParentToEmpty() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeAsChild(root); root.removeChild(2); assertEquals(Optional.empty(), node.getParent()); } @Test public void removeChildIndexRemovesNodeFromChildrenCollection() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeAsChild(root); root.removeChild(2); assertFalse(root.getChildren().contains(node)); } @Test(expected = UnsupportedOperationException.class) public void addThrowsExceptionIfNodeHasParent() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeAsChild(root); root.addChild(node); } @Test public void moveAllChildrenToAddsAtSpecifiedPosition() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = new TreeNodeTestData.TreeNodeMock(); root.addChild(node); TreeNodeTestData.TreeNodeMock child1 = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock child2 = new TreeNodeTestData.TreeNodeMock(); node.addChild(child1); node.addChild(child2); node.moveAllChildrenTo(root, 0); assertEquals(Arrays.asList(child1, child2, node), root.getChildren()); } @Test public void moveAllChildrenToChangesParent() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = new TreeNodeTestData.TreeNodeMock(); root.addChild(node); TreeNodeTestData.TreeNodeMock child1 = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock child2 = new TreeNodeTestData.TreeNodeMock(); node.addChild(child1); node.addChild(child2); node.moveAllChildrenTo(root, 0); assertEquals(root, child1.getParent().get()); assertEquals(root, child2.getParent().get()); } @Test(expected = UnsupportedOperationException.class) public void moveAllChildrenToDescendantThrowsException() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeAsChild(root); root.moveAllChildrenTo(node, 0); } @Test public void sortChildrenSortsInFirstLevel() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock child1 = new TreeNodeTestData.TreeNodeMock("a"); TreeNodeTestData.TreeNodeMock child2 = new TreeNodeTestData.TreeNodeMock("b"); TreeNodeTestData.TreeNodeMock child3 = new TreeNodeTestData.TreeNodeMock("c"); root.addChild(child2); root.addChild(child3); root.addChild(child1); root.sortChildren((o1, o2) -> o1.getName().compareToIgnoreCase(o2.getName()), false); assertEquals(Arrays.asList(child1, child2, child3), root.getChildren()); } @Test public void sortChildrenRecursiveSortsInDeeperLevel() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeInSimpleTree(root); TreeNodeTestData.TreeNodeMock child1 = new TreeNodeTestData.TreeNodeMock("a"); TreeNodeTestData.TreeNodeMock child2 = new TreeNodeTestData.TreeNodeMock("b"); TreeNodeTestData.TreeNodeMock child3 = new TreeNodeTestData.TreeNodeMock("c"); node.addChild(child2); node.addChild(child3); node.addChild(child1); root.sortChildren((o1, o2) -> o1.getName().compareToIgnoreCase(o2.getName()), true); assertEquals(Arrays.asList(child1, child2, child3), node.getChildren()); } @Test public void copySubtreeCopiesChildren() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeAsChild(root); TreeNodeTestData.TreeNodeMock copiedRoot = root.copySubtree(); assertEquals(Optional.empty(), copiedRoot.getParent()); assertFalse(copiedRoot.getChildren().contains(node)); assertEquals(root.getNumberOfChildren(), copiedRoot.getNumberOfChildren()); } @Test public void addChildSomewhereInTreeInvokesChangeEvent() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeInComplexTree(root); root.subscribeToDescendantChanged(subscriber); node.addChild(new TreeNodeTestData.TreeNodeMock()); verify(subscriber).accept(node); } @Test public void moveNodeSomewhereInTreeInvokesChangeEvent() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeInComplexTree(root); TreeNodeTestData.TreeNodeMock oldParent = node.getParent().get(); root.subscribeToDescendantChanged(subscriber); node.moveTo(root); verify(subscriber).accept(root); verify(subscriber).accept(oldParent); } @Test public void removeChildSomewhereInTreeInvokesChangeEvent() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeInComplexTree(root); TreeNodeTestData.TreeNodeMock child = node.addChild(new TreeNodeTestData.TreeNodeMock()); root.subscribeToDescendantChanged(subscriber); node.removeChild(child); verify(subscriber).accept(node); } @Test public void removeChildIndexSomewhereInTreeInvokesChangeEvent() { TreeNodeTestData.TreeNodeMock root = new TreeNodeTestData.TreeNodeMock(); TreeNodeTestData.TreeNodeMock node = TreeNodeTestData.getNodeInComplexTree(root); node.addChild(new TreeNodeTestData.TreeNodeMock()); root.subscribeToDescendantChanged(subscriber); node.removeChild(0); verify(subscriber).accept(node); } private static class WrongTreeNodeImplementation extends TreeNode<TreeNodeTestData.TreeNodeMock> { // This class is a wrong derived class of TreeNode<T> // since it does not extends TreeNode<WrongTreeNodeImplementation> // See test constructorChecksThatClassImplementsCorrectInterface public WrongTreeNodeImplementation() { super(TreeNodeTestData.TreeNodeMock.class); } @Override public TreeNodeTestData.TreeNodeMock copyNode() { return null; } } }