package org.threadly.concurrent.collections; import static org.junit.Assert.*; import static org.threadly.TestConstants.*; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.NoSuchElementException; @SuppressWarnings("javadoc") public class ListTests { public static void populateIntStrings(List<String> testList, int qty) { for (int i = 0; i < qty; i++) { String str = Integer.toString(i); testList.add(str); } } public static void sizeTest(List<String> testList) { for (int i = 0; i < TEST_QTY; i++) { assertEquals(i, testList.size()); testList.add("testStr"); assertEquals(i + 1, testList.size()); } for (int i = TEST_QTY; i >= 0; i--) { assertEquals(i, testList.size()); if (i != 0) { testList.remove(0); } } } public static void isEmptyTest(List<String> testList) { assertTrue(testList.isEmpty()); testList.add("foo"); assertFalse(testList.isEmpty()); testList.add("foo"); assertFalse(testList.isEmpty()); testList.remove(0); assertFalse(testList.isEmpty()); testList.remove(0); assertTrue(testList.isEmpty()); } public static void addNullTest(List<String> testList) { assertFalse(testList.add(null)); } public static void addAllTest(List<String> testList) { List<String> toAddList = new ArrayList<>(TEST_QTY); // verify with empty list first assertFalse(testList.addAll(toAddList)); populateIntStrings(toAddList, TEST_QTY); testList.addAll(toAddList); assertEquals(TEST_QTY, testList.size()); assertTrue(testList.containsAll(toAddList)); Iterator<String> it = toAddList.iterator(); Iterator<String> testIt = testList.iterator(); while (it.hasNext()) { assertTrue(it.next() == testIt.next()); } } public static void setFail(List<String> testList) { try { testList.set(1, "foo"); fail("Exception should have thrown"); } catch (IndexOutOfBoundsException e) { // expected } try { testList.set(-1, "foo"); fail("Exception should have thrown"); } catch (IndexOutOfBoundsException e) { // expected } } public static void addIndexTest(List<String> testList) { for (int i = 0; i < TEST_QTY; i++) { String str = Integer.toString(i); testList.add(i, str); } for (int i = 0; i < TEST_QTY; i++) { assertEquals(Integer.toString(i), testList.get(i)); } // add a second set of items to the front for (int i = 0; i < TEST_QTY; i++) { String str = Integer.toString(i); testList.add(i, str); } // add a third set of items to the end for (int i = 0; i < TEST_QTY; i++) { String str = Integer.toString(i); testList.add(testList.size(), str); } for (int i = 0; i < 3; i++) { for (int j = 0; j < TEST_QTY; j++) { int testIndex = j + (TEST_QTY * i); assertEquals(Integer.toString(j), testList.get(testIndex)); } } } public static void addIndexFail(List<String> testList) { try { testList.add(1, "foo"); fail("Exception should have thrown"); } catch (IndexOutOfBoundsException e) { // expected } try { testList.add(-1, "foo"); fail("Exception should have thrown"); } catch (IndexOutOfBoundsException e) { // expected } } public static void addAllIndexTest(List<String> testList) { List<String> toAddList = new ArrayList<>(TEST_QTY); // verify with empty list first assertFalse(testList.addAll(0, toAddList)); testList.add("foo"); testList.add("bar"); populateIntStrings(toAddList, TEST_QTY); testList.addAll(1, toAddList); assertEquals(TEST_QTY + 2, testList.size()); assertTrue(testList.containsAll(toAddList)); assertEquals(1, testList.indexOf(Integer.toString(0))); assertEquals(TEST_QTY, testList.indexOf(Integer.toString(TEST_QTY - 1))); Iterator<String> it = toAddList.iterator(); Iterator<String> testIt = testList.iterator(); assertTrue(testIt.next().equals("foo")); while (it.hasNext()) { assertTrue(it.next() == testIt.next()); } assertTrue(testIt.next().equals("bar")); } public static void addAllIndexFail(List<String> testList) { List<String> toAdd = new ArrayList<>(1); toAdd.add("foo"); try { testList.addAll(1, toAdd); fail("Exception should have thrown"); } catch (IndexOutOfBoundsException e) { // expected } try { testList.addAll(-1, toAdd); fail("Exception should have thrown"); } catch (IndexOutOfBoundsException e) { // expected } } public static void getTest(List<String> testList) { List<String> comparisionList = new ArrayList<>(TEST_QTY); for (int i = 0; i < TEST_QTY; i++) { String str = Integer.toString(i); comparisionList.add(str); testList.add(str); assertEquals(str, testList.get(i)); } for (int i = 0; i < TEST_QTY; i++) { assertEquals(comparisionList.get(i), testList.get(i)); } } public static void indexOfTest(List<String> testList) { List<String> comparisionList = new ArrayList<>(TEST_QTY * 2); for (int i = 0; i < TEST_QTY; i++) { String str = Integer.toString(i); comparisionList.add(str); comparisionList.add(str); testList.add(str); testList.add(str); } for (int i = 0; i < TEST_QTY; i++) { String str = Integer.toString(i); assertEquals(comparisionList.indexOf(str), testList.indexOf(str)); } assertEquals(-1, testList.indexOf("foobar")); } public static void lastIndexOfTest(List<String> testList) { List<String> comparisionList = new ArrayList<>(TEST_QTY * 2); for (int i = 0; i < TEST_QTY; i++) { String str = Integer.toString(i); comparisionList.add(str); comparisionList.add(str); testList.add(str); testList.add(str); } for (int i = 0; i < TEST_QTY; i++) { String str = Integer.toString(i); assertEquals(comparisionList.lastIndexOf(str), testList.lastIndexOf(str)); } assertEquals(-1, testList.lastIndexOf("foobar")); } public static void containsTest(List<String> testList) { populateIntStrings(testList, TEST_QTY); for (int i = 0; i < TEST_QTY; i++) { String str = Integer.toString(i); assertTrue(testList.contains(str)); } for (int i = TEST_QTY + 1; i < TEST_QTY * 2; i++) { String str = Integer.toString(i); assertFalse(testList.contains(str)); } } public static void containsAllTest(List<String> testList) { List<String> comparisionList = new ArrayList<>(TEST_QTY + 1); assertTrue(testList.containsAll(comparisionList)); comparisionList.add("bar"); assertFalse(testList.containsAll(comparisionList)); testList.add("bar"); assertTrue(testList.containsAll(comparisionList)); for (int i = 0; i < TEST_QTY; i++) { String str = Integer.toString(i); comparisionList.add(str); assertFalse(testList.containsAll(comparisionList)); testList.add(str); assertTrue(testList.containsAll(comparisionList)); } testList.add("foobar"); assertTrue(testList.containsAll(comparisionList)); } public static void toArrayTest(List<String> testList) { assertArrayEquals(testList.toArray(), new String[0]); String[] compare = new String[TEST_QTY]; for (int i = 0; i < TEST_QTY; i++) { String str = Integer.toString(i); compare[i] = str; testList.add(str); } assertArrayEquals(testList.toArray(), compare); String[] expectedResult = compare; // reset for next test compare = new String[TEST_QTY]; String[] result = testList.toArray(compare); assertArrayEquals(result, expectedResult); assertTrue(result == compare); result = testList.toArray(new String[0]); assertArrayEquals(result, expectedResult); } public static void clearTest(List<String> testList) { populateIntStrings(testList, TEST_QTY); assertEquals(TEST_QTY, testList.size()); testList.clear(); assertEquals(0, testList.size()); } public static void removeMissingObjectTest(List<String> testList) { assertFalse(testList.remove(new Object())); assertFalse(testList.remove("foo")); } public static void removeObjectTest(List<String> testList) { populateIntStrings(testList, TEST_QTY); boolean flip = false; int removed = 0; for (int i = 0; i < TEST_QTY; i++) { if (flip) { String str = Integer.toString(i); assertTrue(testList.remove(str)); assertFalse(testList.contains(str)); removed++; flip = false; } else { flip = true; } } assertEquals(TEST_QTY - removed, testList.size()); } public static void removeAllTest(List<String> testList) { List<String> toRemoveList = new ArrayList<>(TEST_QTY); // verify returned false on no modification assertFalse(testList.removeAll(toRemoveList)); List<String> comparisonList = new ArrayList<>(TEST_QTY); boolean flip = false; for (int i = 0; i < TEST_QTY; i++) { String str = Integer.toString(i); testList.add(str); comparisonList.add(str); if (flip) { toRemoveList.add(str); flip = false; } else { flip = true; } } List<String> noOpList = new ArrayList<>(2); noOpList.add("foo"); noOpList.add("bar"); assertFalse(testList.removeAll(noOpList)); assertEquals(TEST_QTY, testList.size()); assertTrue(testList.removeAll(toRemoveList)); assertEquals(TEST_QTY - toRemoveList.size(), testList.size()); Iterator<String> it = toRemoveList.iterator(); while (it.hasNext()) { assertFalse(testList.contains(it.next())); } comparisonList.removeAll(toRemoveList); // do operation on comparison list assertTrue(testList.containsAll(comparisonList)); // verify nothing additional was removed } public static void removeIndexTest(List<String> testList) { int testQty = Math.max(4, TEST_QTY); populateIntStrings(testList, testQty); List<String> removedItems = new LinkedList<>(); String removedItem = testList.remove(testQty - 1); assertTrue(removedItem.equals(Integer.toString(testQty - 1))); removedItems.add(removedItem); removedItem = testList.remove(testQty / 2); assertTrue(removedItem.equals(Integer.toString(testQty / 2))); removedItems.add(removedItem); removedItem = testList.remove(0); assertTrue(removedItem.equals(Integer.toString(0))); removedItems.add(removedItem); Iterator<String> it = removedItems.iterator(); while (it.hasNext()) { assertFalse(testList.contains(it.next())); } } public static void removeIndexFail(List<String> testList) { try { testList.remove(1); fail("Exception should have thrown"); } catch (IndexOutOfBoundsException e) { // expected } try { testList.remove(-1); fail("Exception should have thrown"); } catch (IndexOutOfBoundsException e) { // expected } } public static void retainAllTest(List<String> testList) { // verify with empty list assertFalse(testList.retainAll(Collections.emptyList())); populateIntStrings(testList, TEST_QTY); assertTrue(testList.retainAll(Collections.emptyList())); assertEquals(0, testList.size()); populateIntStrings(testList, TEST_QTY); assertFalse(testList.retainAll(testList)); assertFalse(testList.retainAll(new ArrayList<>(testList))); List<String> toRetainList = new ArrayList<>(TEST_QTY / 2); populateIntStrings(toRetainList, TEST_QTY / 2); assertTrue(testList.retainAll(toRetainList)); assertEquals(TEST_QTY / 2, testList.size()); assertTrue(toRetainList.containsAll(testList)); } public static void iteratorTest(List<String> testList) { List<String> comparisionList = new ArrayList<>(TEST_QTY); for (int i = 0; i < TEST_QTY; i++) { String str = Integer.toString(i); comparisionList.add(str); testList.add(str); } Iterator<String> clIt = comparisionList.iterator(); Iterator<String> testIt = testList.iterator(); while (clIt.hasNext()) { assertTrue(testIt.hasNext()); assertEquals(clIt.next(), testIt.next()); } boolean flip = false; clIt = comparisionList.iterator(); testIt = testList.iterator(); while (clIt.hasNext()) { clIt.next(); testIt.next(); if (flip) { clIt.remove(); testIt.remove(); flip = false; } else { flip = true; } } assertTrue(comparisionList.equals(testList)); } public static void listIteratorTest(List<String> testList) { List<String> comparisionList = new ArrayList<>(TEST_QTY); for (int i = 0; i < TEST_QTY; i++) { String str = Integer.toString(i); comparisionList.add(str); testList.add(str); } // forward ListIterator<String> clIt = comparisionList.listIterator(0); ListIterator<String> testIt = testList.listIterator(0); assertFalse(testIt.hasPrevious()); while (clIt.hasNext()) { assertTrue(testIt.hasNext()); assertEquals(clIt.next(), testIt.next()); assertEquals(clIt.nextIndex(), testIt.nextIndex()); //assertEquals(clIt.previousIndex(), testIt.previousIndex()); } // backwards clIt = comparisionList.listIterator(comparisionList.size()); testIt = testList.listIterator(testList.size()); assertFalse(testIt.hasNext()); while (clIt.hasPrevious()) { assertTrue(testIt.hasPrevious()); assertEquals(clIt.previous(), testIt.previous()); assertEquals(clIt.nextIndex(), testIt.nextIndex()); assertEquals(clIt.previousIndex(), testIt.previousIndex()); } // modify int iteration = Integer.MAX_VALUE; boolean flip = false; clIt = comparisionList.listIterator(); testIt = testList.listIterator(); while (clIt.hasNext()) { iteration--; clIt.next(); testIt.next(); if (flip) { clIt.remove(); testIt.remove(); flip = false; } else { String value = Integer.toHexString(iteration); clIt.add(value); testIt.add(value); flip = true; } } assertTrue(comparisionList.equals(testList)); } public static void listIteratorFail(List<String> testList) { ListIterator<String> it = testList.listIterator(); try { it.next(); fail("Exception should have been thrown"); } catch (NoSuchElementException e) { // expected } it = testList.listIterator(); try { it.previous(); fail("Exception should have been thrown"); } catch (NoSuchElementException e) { // expected } populateIntStrings(testList, TEST_QTY); it = testList.listIterator(); try { it.previous(); fail("Exception should have been thrown"); } catch (NoSuchElementException e) { // expected } it = testList.listIterator(testList.size()); try { it.next(); fail("Exception should have been thrown"); } catch (NoSuchElementException e) { // expected } } public static void equalsTest(List<String> testList) { assertFalse(testList.equals(new Object())); List<String> comparisionList = new ArrayList<>(TEST_QTY); for (int i = 0; i < TEST_QTY; i++) { String str = Integer.toString(i); comparisionList.add(str); testList.add(str); assertTrue(testList.equals(comparisionList)); } // easy test assertTrue(testList.equals(testList)); String foo = "foo"; comparisionList.add(foo); assertFalse(testList.equals(comparisionList)); testList.add(foo); assertTrue(testList.equals(comparisionList)); testList.add(foo); assertFalse(testList.equals(comparisionList)); } public static void hashCodeTest(List<String> testList) { List<String> comparisionList = new ArrayList<>(TEST_QTY); assertEquals(testList.hashCode(), comparisionList.hashCode()); for (int i = 0; i < TEST_QTY; i++) { String str = Integer.toString(i); comparisionList.add(str); testList.add(str); assertEquals(testList.hashCode(), comparisionList.hashCode()); } String foo = "foo"; comparisionList.add(foo); assertNotEquals(testList.hashCode(), comparisionList.hashCode()); testList.add(foo); assertEquals(testList.hashCode(), comparisionList.hashCode()); testList.add(foo); assertNotEquals(testList.hashCode(), comparisionList.hashCode()); assertEquals(testList.hashCode(), testList.subList(0, testList.size()).hashCode()); } public static void subListTest(List<String> testList) { int testQty = Math.max(4, TEST_QTY); populateIntStrings(testList, testQty); List<String> completeList = testList.subList(0, testQty); assertEquals(testQty, completeList.size()); Iterator<String> it1 = testList.iterator(); Iterator<String> it2 = completeList.iterator(); for (int i = 0; i < testQty; i++) { assertEquals(it1.next(), it2.next()); } List<String> smallList = testList.subList(0, 1); assertEquals(1, smallList.size()); assertEquals(testList.get(0), smallList.get(0)); smallList = testList.subList(testQty - 1, testQty); assertEquals(1, smallList.size()); assertEquals(testList.get(testQty - 1), smallList.get(0)); int halfQty = testQty / 2; List<String> mediumList = testList.subList(1, halfQty); assertEquals(mediumList.size(), halfQty - 1); it1 = mediumList.iterator(); for (int i = 1; i < halfQty; i++) { assertEquals(testList.get(i), it1.next()); } } public static void subListFail(List<String> testList) { populateIntStrings(testList, TEST_QTY); try { testList.subList(-1, 0); fail("Exception should have been thrown"); } catch (IndexOutOfBoundsException e) { // expected } try { testList.subList(0, -1); fail("Exception should have been thrown"); } catch (IndexOutOfBoundsException e) { // expected } try { testList.subList(2, 0); fail("Exception should have been thrown"); } catch (IndexOutOfBoundsException e) { // expected } try { testList.subList(0, TEST_QTY + 1); fail("Exception should have been thrown"); } catch (IndexOutOfBoundsException e) { // expected } try { testList.subList(TEST_QTY + 10, TEST_QTY); fail("Exception should have been thrown"); } catch (IndexOutOfBoundsException e) { // expected } } }