//Copyright (c) Corporation for National Research Initiatives package javatests; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.NoSuchElementException; /** * @author updikca1 */ public abstract class ListTest { public static ListTest getArrayListTest(final boolean makeReadOnly) { return new ListTest() { public List newInstance(Collection c) { List l = null; if(c == null) { l = new ArrayList(); } else { l = new ArrayList(c); } return (makeReadOnly) ? Collections.unmodifiableList(l) : l; } public boolean isReadOnly() { return makeReadOnly; } }; } public static void verifyImutability(List l) { String message = "Expected UnsupportedOperationException."; try { l.add(0, new Integer(0)); TestSupport.assertThat(false, message); } catch (UnsupportedOperationException e) {} try { l.add(new Integer(0)); TestSupport.assertThat(false, message); } catch (UnsupportedOperationException e) {} try { l.addAll(null); TestSupport.assertThat(false, message); } catch (UnsupportedOperationException e) {} try { l.addAll(0, null); TestSupport.assertThat(false, message); } catch (UnsupportedOperationException e) {} try { l.clear(); TestSupport.assertThat(false, message); } catch (UnsupportedOperationException e) {} try { l.remove(0); TestSupport.assertThat(false, message); } catch (UnsupportedOperationException e) {} try { l.remove(new Object()); TestSupport.assertThat(false, message); } catch (UnsupportedOperationException e) {} try { l.removeAll(null); TestSupport.assertThat(false, message); } catch (UnsupportedOperationException e) {} try { l.retainAll(null); TestSupport.assertThat(false, message); } catch (UnsupportedOperationException e) {} try { l.set(0,new Integer(0)); TestSupport.assertThat(false, message); } catch (UnsupportedOperationException e) {} } private final List nullList; protected List defaultList() { List l = new ArrayList(); for (int i = 0; i < 4; i++) { l.add(new Integer(i)); } return newInstance(l); } /** * Implementations must supply an empty list if the collection is null. * @param c Initial collection or null for empty. * @return the List instance */ public List newInstance(Collection c) { throw new UnsupportedOperationException("This method must be overridden"); } /** * @return true if the list is read-only (like PyTuple) */ public boolean isReadOnly() { throw new UnsupportedOperationException("This method must be overridden"); } { nullList = newInstance(Arrays.asList(new Object[] {null})); } public void testAll() { test_get(); test_equals(); test_size(); test_contains(); test_containsAll(); try { defaultList().hashCode(); test_hashCode(); } catch (Exception e) { // skip unhashable types } test_subList(); test_lastIndexOf(); test_listIterator(); test_toArray(); test_toArray_typed(); if(!isReadOnly()) { test_add(); test_add_index(); test_set(); test_clear(); test_addAll(); test_addAll_index(); test_remove(); test_remove_index(); test_removeAll(); test_retainAll(); } else { verifyImutability(newInstance(null)); } } /** Tests get(int index) */ public void test_get() { TestSupport.assertThat(defaultList().get(0).equals(new Integer(0)), "get() did not return expected value of Integer(0)"); try { defaultList().get(-1); TestSupport.assertThat(false, "get() did not throw IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException e) {} try { defaultList().get(-1); TestSupport.assertThat(false, "get() did not throw IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException e) {} } /** Tests set(int index, Object element) */ public void test_set() { try { newInstance(null).set(-1, "spam"); TestSupport.assertThat(false, "get() did not throw IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException e) {} try { newInstance(null).set(0, "spam"); TestSupport.assertThat(false, "set() did not throw IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException e) {} List a = defaultList(); a.set(a.size() - 1 , "spam"); TestSupport.assertThat(a.get(a.size() - 1).equals("spam"), "set() object was not retrieved via get()"); } /** Tests add(Object o) */ public void test_add() { List a = newInstance(null); for (int i = 0; i < 4; i++) { a.add(new Integer(i)); } TestSupport.assertEquals(a, defaultList(), "add(Object o) failed"); } /** Tests isEmpty() */ public void test_isEmpty() { List a = newInstance(null); TestSupport.assertThat(a.isEmpty(), "isEmpty() is false on an emtpy List"); a.addAll(defaultList()); TestSupport.assertThat(!a.isEmpty(), "isEmpty() is true on a non-empty List)" ); a.clear(); TestSupport.assertThat(a.isEmpty(), "isEmpty() is false on an emtpy List"); } /** Tests size() */ public void test_size() { List b = newInstance(null); TestSupport.assertThat(b.size() == 0, "empty list size was not 0"); TestSupport.assertThat(defaultList().size() == 4, "default list did not have a size of 4"); } /** Tests add(int index, Object element) */ public void test_add_index() { List a = newInstance(null); List b = defaultList(); for (int i = 0; i < b.size(); i++) { a.add(i, b.get(i)); } try { a.add(a.size() + 1, new Integer(a.size() + 1)); TestSupport.assertThat(false, "expected IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException e) {} try { a.add(-1, new Integer(-1)); TestSupport.assertThat(false, "expected IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException e) {} } /** Tests equals(Object o)*/ public void test_equals() { TestSupport.assertEquals(defaultList(), defaultList(), "Identical lists weren't equal()"); TestSupport.assertNotEquals(newInstance(null), defaultList(), "Different lists were equal()"); TestSupport.assertNotEquals(newInstance(null), new Object(), "List was equal to a non-List type"); } /** Tests addAll(Collection c) */ public void test_addAll() { List a = defaultList(); List b = defaultList(); TestSupport.assertThat(a.addAll(b) == true, "Mutating addAll(Collection) returned false"); TestSupport.assertThat(a.addAll(newInstance(null)) == false, "Idempotent addAll(Collection) returned true"); TestSupport.assertThat(b.addAll(b) == true, "Mutating addAll(Collection) returned false"); TestSupport.assertEquals(a, b, "Expected equal objects from addAll(collection)"); TestSupport.assertThat(a.size() == 8, "Expected List to have size 8 after addAll(Collection)"); } /** Tests indexOf(Object o) */ public void indexOf() { TestSupport.assertThat(defaultList().indexOf(new Integer(3)) == 3, "indexOf(3) did not return 3"); TestSupport.assertThat(defaultList().indexOf(new Integer(42)) == -1, "indexOf() non-existing entry did not return -1"); TestSupport.assertThat(defaultList().indexOf(null) == -1, "indexOf() non-existing null did not return -1"); } /** Tests contains(Object o) */ public void test_contains() { TestSupport.assertThat(defaultList().contains(new Integer(42)) == false, "contains() returned true for non-existing entry"); TestSupport.assertThat(defaultList().contains(new Integer(0)) == true, "contains() returned false for existing entry"); TestSupport.assertThat(nullList.contains(null) == true, "contains() returned false for existing null entry"); TestSupport.assertThat(defaultList().contains(null) == false, "contains() returned true for non-existing null entry"); } /** Tests remove(Object o) */ public void test_remove() { List a = defaultList(); a.add(null); TestSupport.assertThat(a.remove(null) == true, "remove() existing null entry returned false"); TestSupport.assertThat(a.remove(null) == false, "remove() non-existing null entry returned false"); a.add("spam"); TestSupport.assertThat(a.remove("spam") == true, "remove() existing entry returned false"); TestSupport.assertThat(a.remove("spam") == false, "remove() non-existing entry returned true"); } /** Tests remove(int index) */ public void test_remove_index() { List a = defaultList(); for (int i = 0, n = a.size(); i < n; i++) { a.remove(0); } TestSupport.assertThat(a.size() == 0, "remove()-d all entries but size() not 0"); try { a.remove(0); TestSupport.assertThat(false, "removing a non-existing index did not throw exception"); } catch(IndexOutOfBoundsException e) {} } /** Tests lastIndexOf(Object o) */ public void test_lastIndexOf() { // avoid calling any mutable methods List l = new ArrayList(defaultList()); l.add(new Integer(0)); // now get the immutable version List a = newInstance(l); TestSupport.assertThat(a.lastIndexOf(new Integer(0)) == 4, "lastIndexOf() did not return 4"); TestSupport.assertThat(a.lastIndexOf(new Integer(42)) == -1, "lastIndexOf() non-existing value did not return -1"); } /** Tests removeAll(Collection c) */ public void test_removeAll() { List a = defaultList(); TestSupport.assertThat(a.removeAll(a) == true, "mutating removeAll() did not return true"); TestSupport.assertThat(a.removeAll(a) == false, "idempotent removeAll did not return false"); TestSupport.assertThat(a.removeAll(nullList) == false, "idempotent removeAll did not return false"); List yanl = newInstance(null); yanl.addAll(nullList); TestSupport.assertThat(yanl.removeAll(nullList) == true, "mutating removeAll() did not return true"); TestSupport.assertThat(yanl.size() == 0, "empty list had non-zero size"); TestSupport.assertThat(yanl.removeAll(newInstance(null)) == false, "idempotent removeAll did not return false"); } /** Tests addAll(int index, Collection c) */ public void test_addAll_index() { List a = defaultList(); List b = newInstance(null); TestSupport.assertThat(b.addAll(0,a) == true, "mutating addAll(index, Collection) did not return true"); TestSupport.assertEquals(a, b, "addAll(index, Collection) instances failed equals test"); TestSupport.assertThat(a.addAll(0, newInstance(null)) == false, "idempotent addAll(index, Collection) did not return false"); TestSupport.assertThat(b.addAll(0,b) == true, "mutating addAll(index, Collection) did not return true"); // Since PyObjectList has some specific handling when it detects // addAll on a PySequenceList, make sure the general case works. b = newInstance(null); b.addAll(new ArrayList(defaultList())); TestSupport.assertEquals(defaultList(), b, "addAll(index, ) failed equals test"); } /** Tests hashCode() */ public void test_hashCode() { List a = defaultList(); TestSupport.assertThat(a.hashCode() == defaultList().hashCode(), "Instances with same internal state have different hashcode"); TestSupport.assertThat(a.hashCode() != newInstance(null).hashCode(), "Instances with different internal state have the same hashcode"); if (isReadOnly() == false) { List b = newInstance(null); b.addAll(a); b.remove(0); TestSupport.assertThat(a.hashCode()!= b.hashCode(), "Instances with different internal state have the same hashcode"); } } /** Tests clear() */ public void test_clear() { List a = defaultList(); a.clear(); TestSupport.assertThat(a.size() == 0, "clear()-ed list did not have size of 0"); } /** Tests subList(int fromIndex, int toIndex) */ public void test_subList() { List a = defaultList(); TestSupport.assertThat((a.subList(0, a.size()) != a), "subList() returned the same instance"); TestSupport.assertEquals(a.subList(0, a.size()), a, "Complete subList() did not equal original List"); TestSupport.assertThat(a.subList(0,0).size() == 0, "empty subList had non-zero size"); try { a.subList(-1,1); TestSupport.assertThat(false, "Expected IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException e) {} try { a.subList(1,0); TestSupport.assertThat(false, "Expected IllegalArgumentException"); } catch (IllegalArgumentException e) {} try { a.subList(0,a.size() + 1); TestSupport.assertThat(false, "Expected IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException e) {} if (!isReadOnly()) { a.subList(0, a.size()).clear(); TestSupport.assertThat(a.size() == 0, "clear()-ed sublist did not have zero size"); List c = newInstance(null); c.addAll(defaultList()); List d = c.subList(1,3); TestSupport.assertThat(d.size() == 2, "Expected subList to have size of 2"); TestSupport.assertThat(c.set(1,"canned").equals(new Integer(1)), "subList.set() did not return Integer(1) from index 1" + " of defaultList"); TestSupport.assertThat(d.get(0).equals("canned"), "subList does not update with changes to parent"); d.set(0,"spam"); TestSupport.assertThat(c.get(1).equals("spam"), "parent does not update with changes to subList child"); } else { List b = a.subList(0, a.size()); verifyImutability(b); } } /** Tests retainAll(Collection c) */ public void test_retainAll() { List a = defaultList(); a.retainAll(defaultList()); TestSupport.assertEquals(a, defaultList(), "retainAll() does not equal original list"); a = defaultList(); a.retainAll(newInstance(null)); TestSupport.assertThat(a.size() == 0, "retainAll())does not have size of zero"); a = defaultList(); a.remove(0); a.remove(0); a.add(new Integer(4)); a.add(new Integer(5)); List b = newInstance(null); b.add(new Integer(2)); b.add(new Integer(3)); a.retainAll(b); TestSupport.assertEquals(a, b, "retainAll() on overlap of indices [2,3] did not return that List"); } /** Tests containsAll(Collection c) */ public void test_containsAll() { TestSupport.assertThat(defaultList().containsAll(defaultList()), "containsAll( was false"); TestSupport.assertThat(defaultList().containsAll(newInstance(null)), "containsAll() was false"); TestSupport.assertThat(newInstance(null).containsAll(defaultList()) == false, "containsAll() returned true"); TestSupport.assertThat(defaultList().containsAll(defaultList().subList(1,3)), "containsAll() was false"); } /** Tests iterator() */ public void test_iterator() { TestSupport.assertThat(newInstance(null).iterator().hasNext() == false, "Iterator for empty list thinks it hasNext()"); try { newInstance(null).iterator().next(); TestSupport.assertThat(false, "expected NoSuchElementException"); } catch (NoSuchElementException e) {} List a = defaultList(); int i = 0; for (Iterator iter = a.iterator(); iter.hasNext(); ) { TestSupport.assertThat(iter.next() == a.get(i++), "Iterator next() failed identity test"); } TestSupport.assertThat(i == a.size(), "Iterator did not iterator over entire list"); } public void test_listIterator() { ListIterator li = newInstance(null).listIterator(); TestSupport.assertThat(li.hasNext() == false, "ListIterator.hasNext() is true for empty List"); TestSupport.assertThat(li.hasPrevious() == false, "ListIterator.hasPrevious() is true for empty List"); try { li.next(); TestSupport.assertThat(false, "expected NoSuchElementException"); } catch (NoSuchElementException e) {} try { li.previous(); TestSupport.assertThat(false, "expected NoSuchElementException"); } catch (NoSuchElementException e) {} // Appears bug was fixed from 1.3 to 1.4. Code it to pass either way. int nextIndex = li.nextIndex(); TestSupport.assertThat(nextIndex == -1 || nextIndex == 0, "ListIterator.nextIndex() on empty List did not return 0 " + "(java 1.4) or did not return -1 (java 1.3)"); // Likewise... int prevIndex = li.previousIndex(); TestSupport.assertThat(prevIndex == -1 || prevIndex == -2, "ListIterator.previousIndex() on empty List did not return -1 " + "(java 1.4) or -2 (java 1.3)"); List l = new ArrayList(); l.add(new Integer(1)); li = newInstance(l).listIterator(); TestSupport.assertThat(li.hasPrevious() == false, "ListIterator.hasPrevious() is true with nothing previous"); TestSupport.assertThat(li.hasNext() == true, "ListIterator.hasNext() is false with next present"); TestSupport.assertThat(li.next().equals(new Integer(1)), "ListIterator.next() did not return expected Integer(1)"); if (!isReadOnly()) { li.remove(); TestSupport.assertThat(li.hasNext() == false, "ListIterator.hasNext() is true for empty List"); TestSupport.assertThat(li.hasPrevious() == false, "ListIterator.hasPrevious() is true for empty List"); try { li.set(new Integer(42)); TestSupport.assertThat(false, "expected IllegalStateException"); } catch (IllegalStateException e) {} try { li.remove(); TestSupport.assertThat(false, "expected IllegalStateException"); } catch (IllegalStateException e) {} } l = new ArrayList(); l.add(new Integer(0)); l.add(new Integer(1)); l.add(new Integer(2)); li = newInstance(l).listIterator(); for (int i = 0, n = l.size(); i < n; i++) { TestSupport.assertThat(li.next().equals(new Integer(i)), "ListIterator.previous did not return expected value"); } while (!isReadOnly() && li.hasNext()) { li.next(); li.set(new Integer(42)); TestSupport.assertThat(li.previous().equals(new Integer(42)), "ListIterator.previous() did not return the value that was set()"); li.remove(); } if(isReadOnly()) { li = newInstance(null).listIterator(); } li = defaultList().listIterator(2); TestSupport.assertThat(li.next().equals(new Integer(2)), "List.listIteraor(index) did not return expected value"); TestSupport.assertThat(li.next().equals(new Integer(3)), "List.listIteraor(index) did not return expected value"); TestSupport.assertThat(li.hasNext() == false, "listIterator.hasNext() at end of list returned true"); } /** Tests toArray() */ public void test_toArray() { Object[] intObjArray = new Integer[] { new Integer(0), new Integer(1), new Integer(2), new Integer(3)}; TestSupport.assertThat(Arrays.equals(defaultList().toArray(), intObjArray), "toArray() did not return the expected Integer[] array"); } /** Tests toArray(Object[] a) */ public void test_toArray_typed() { Object[] intObjArray = new Integer[] { new Integer(0), new Integer(1), new Integer(2), new Integer(3)}; TestSupport.assertThat(Arrays.equals( defaultList().toArray(new Integer[] {}), intObjArray), "toArray(Integer[]) did not return the expected Integer[] array"); } // Can't test clone since it's not visible, but it is from jython. // /** Tests clone() */ // public void test_clone() { // List a = defaultList(); // TestSupport.assertEquals(((Object)a).clone(), a, // "clone() was not equal to original"); // TestSupport.assertThat(a.clone() != a, // "clone() returned same instance"); // } }