/******************************************************************************* * Copyright (c) 2014 Open Door Logistics (www.opendoorlogistics.com) * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser Public License v3 * which accompanies this distribution, and is available at http://www.gnu.org/licenses/lgpl.txt ******************************************************************************/ package tests.com.opendoorlogistics.core.utils; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertTrue; import java.util.ArrayList; import java.util.List; import java.util.Random; import org.junit.Test; import com.opendoorlogistics.core.utils.DeepCopier; import com.opendoorlogistics.core.utils.TreeList; public class TreeListTest { private final int length = 100; private final int nbRepeats=10; /** * Test simple add and removal */ @Test public void testSimpleAddRemove() { TreeList<Integer> list = new TreeList<>(false); list.setDebugChecks(true); // add remove root with no child list.add(10); list.removeAt(0); assertEquals(list.size(), 0); // remove root with one child list = new TreeList<>(false); list.setDebugChecks(true); list.insert(0, 10); list.insert(1, 20); list.removeAt(0); assertEquals(20, (int)list.get(0).getValue()); // remove root with two children list = new TreeList<>(false); list.setDebugChecks(true); list.insert(0, 10); list.insert(1, 20); list.insert(0, 5); list.removeAt(1); assertEquals(5, (int)list.get(0).getValue()); assertEquals(20, (int)list.get(1).getValue()); } /** * Test that indices fuction correctly in an unsorted list */ @Test public void testUnsortedIndices() { // insert n integers in random positions Random random = new Random(123); for(int j =0 ; j < nbRepeats ; j++){ TreeList<Integer> list = createUnsorted(random); assertEquals(length, list.size()); assertTrue(isIndicesCorrect(list)); } } /** * Retrieve each node by index and check the node's index equals the * retrieval index * @param list * @return */ private static boolean isIndicesCorrect(TreeList<Integer> list ){ for(int i =0 ;i< list.size() ; i++){ TreeList<Integer>.TreeListNode node = list.get(i); if(i!= node.getIndex()){ return false; } } return true; } /** * Test that extracting the contents via an iterator or via * the indices gives the same results */ @Test public void testIterator(){ Random random = new Random(123); for(int j =0 ; j < nbRepeats ; j++){ TreeList<Integer> list = createUnsorted(random); ArrayList<Integer> fromIt = extractListUsingIterator(list); ArrayList<Integer> fromRandAccess = new ArrayList<>(); for(int i = 0 ; i < list.size() ; i++){ fromRandAccess.add(list.get(i).getValue()); } // check lists retrieved by different methods are equal assertListsEqual(fromIt, fromRandAccess); } } private void assertListsEqual(List<Integer> listA, List<Integer> listB) { assertEquals(listA.size(), listB.size()); for(int i =0 ; i<listA.size() ; i++){ assertTrue(listA.get(i).equals(listB.get(i))); } } private ArrayList<Integer> extractListUsingIterator(TreeList<Integer> list) { ArrayList<Integer> fromIt = new ArrayList<>(); for(TreeList<Integer>.TreeListNode node : list){ fromIt.add(node.getValue()); } return fromIt; } /** * Create an unsorted list * @param random * @return */ private TreeList<Integer> createUnsorted(Random random) { TreeList<Integer> list = new TreeList<>(false); list.setDebugChecks(true); for(int i =0 ;i< length ; i++){ int index = random.nextInt(list.size()+1); list.insert(index, random.nextInt()); } return list; } /** * Test the input list is correctly sorted numerically * @param list * @return */ static boolean isSorted(TreeList<Integer> list ){ for(int j =1 ; j < list.size() ; j++){ if(list.get(j-1).getValue() > list.get(j).getValue()){ return false; } } return true; } /** * Create a sorted list and check it is sorted */ @Test public void testSorted() { Random random = new Random(3456); for(int i =0 ; i < nbRepeats ; i++){ // create sorted and check it is sorted TreeList<Integer> list = createSorted(random); assertTrue(isSorted(list)); assertTrue(isIndicesCorrect(list)); } } /** * Create a sorted list and then remove from it in random * order ensuring the list is still sorted. */ @Test public void testSortedWithRemovals() { Random random = new Random(3456); for(int i =0 ; i < nbRepeats ; i++){ // create sorted, keep on removing and checking still sorted TreeList<Integer> list = createSorted(random); while(list.size() > 0){ removeFromRandomPosition(random, list); assertTrue(isSorted(list)); assertTrue(isIndicesCorrect(list)); } } } private void removeFromRandomPosition(Random random, TreeList<Integer> list) { int index = random.nextInt(list.size()); Object atIndex = list.get(index); Object removed = list.removeAt(index); assertEquals(atIndex, removed); } /** * Create a sorted list and then remove from it in random * order ensuring the list is still sorted. */ @Test public void testSortedWithRemovalsAndInserts() { Random random = new Random(3456); for(int i =0 ; i < nbRepeats ; i++){ TreeList<Integer> list = new TreeList<>(false); list.setDebugChecks(true); for(int j =0 ;j< length ; j++){ if(random.nextBoolean() && list.size()>0){ removeFromRandomPosition(random, list); }else{ int val = random.nextInt(); insertInSortedPosition(list, val); } assertTrue(isSorted(list)); assertTrue(isIndicesCorrect(list)); } } } /** * Create a sorted list * @param random * @return */ private TreeList<Integer> createSorted(Random random) { TreeList<Integer> list = new TreeList<>(false); list.setDebugChecks(true); for(int i =0 ;i< length ; i++){ int value = random.nextInt(); insertInSortedPosition(list, value); } return list; } @Test public void testDeepCopy() { Random random = new Random(123); TreeList<Integer> original = createSorted(random); DeepCopier<Integer> valueCopier = new DeepCopier<Integer>() { @Override public Integer deepCopy(Integer obj) { return obj; } }; TreeList<Integer> copy = original.deepCopy(valueCopier); List<Integer> originalList = extractListUsingIterator(original); List<Integer> copyList = extractListUsingIterator(copy); isIndicesCorrect(copy); assertListsEqual(originalList, copyList); } private void insertInSortedPosition(TreeList<Integer> list, int value) { int found=-1; for(int j =0 ; j < list.size() ; j++){ if(list.get(j).getValue() >= value){ found = j; break; } } if(found == -1){ // add at end found = list.size(); } list.insert(found, value); } @Test public void testSimpleRebuild(){ Random random = new Random(123); for(int i =0 ; i < nbRepeats ; i++){ TreeList<Integer> list = createSorted(random); ArrayList<Integer> before = list.toArrayList(); list.rebuild(); assertTrue(isSorted(list)); assertTrue(isIndicesCorrect(list)); ArrayList<Integer> after = list.toArrayList(); assertTrue(before.equals(after)); } } @Test public void testComplexRebuild(){ Random random = new Random(123); for(int i =0 ; i < nbRepeats ; i++){ TreeList<Integer> list = new TreeList<>(false); list.setDebugChecks(true); for(int j =0 ;j< length ; j++){ if(random.nextBoolean() && list.size()>0){ removeFromRandomPosition(random, list); }else{ int val = random.nextInt(); insertInSortedPosition(list, val); } // test rebuild ArrayList<Integer> before = list.toArrayList(); list.rebuild(); assertTrue(isSorted(list)); assertTrue(isIndicesCorrect(list)); ArrayList<Integer> after = list.toArrayList(); assertTrue(before.equals(after)); } } } @Test public void testAutomaticRebuild(){ Random random = new Random(123); for(int i =0 ; i < nbRepeats ; i++){ TreeList<Integer> list = new TreeList<>(true); list.setDebugChecks(true); for(int j =0 ;j< length ; j++){ if(random.nextBoolean() && list.size()>0){ removeFromRandomPosition(random, list); }else{ int val = random.nextInt(); insertInSortedPosition(list, val); } assertTrue(isSorted(list)); assertTrue(isIndicesCorrect(list)); } } } }