Adds java.util.ListIterator to the emulated JRE collection classes.
Fixes issue #165.
Review by: knorton
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@434 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/super/com/google/gwt/emul/java/util/AbstractList.java b/user/super/com/google/gwt/emul/java/util/AbstractList.java
index 85d5166..ee288fc 100644
--- a/user/super/com/google/gwt/emul/java/util/AbstractList.java
+++ b/user/super/com/google/gwt/emul/java/util/AbstractList.java
@@ -20,7 +20,12 @@
*/
public abstract class AbstractList extends AbstractCollection implements List {
- private final class IteratorImpl implements Iterator {
+ private class IteratorImpl implements Iterator {
+ /*
+ * i is the index of the item that will be returned on the next call to next()
+ * last is the index of the item that was returned on the previous call
+ * to next() or previous (for ListIterator), -1 if no such item exists.
+ */
int i = 0, last = -1;
@@ -32,18 +37,73 @@
if (!hasNext()) {
throw new NoSuchElementException();
}
- return get(last = i++);
- }
+ return get(last = i++);
+ }
public void remove() {
if (last < 0) {
throw new IllegalStateException();
- }
- AbstractList.this.remove(i - 1);
- --i;
+ }
+ AbstractList.this.remove(last);
+ i = last;
last = -1;
}
}
+
+ /**
+ * Implementation of <code>ListIterator</code> for abstract lists.
+ */
+ private final class ListIteratorImpl extends IteratorImpl implements
+ ListIterator {
+ /*
+ * i is the index of the item that will be returned on the next call to next()
+ * last is the index of the item that was returned on the previous call
+ * to next() or previous (for ListIterator), -1 if no such item exists.
+ */
+
+ private ListIteratorImpl() {
+ // Nothing to do
+ }
+
+ private ListIteratorImpl(int start) {
+ int size = AbstractList.this.size();
+ if (start < 0 || start > size) {
+ throw new IndexOutOfBoundsException("Size: " + AbstractList.this.size() + " Index: " + i);
+ }
+ i = start;
+ }
+
+ public void add(Object o) {
+ AbstractList.this.add(i++, o);
+ last = -1;
+ }
+
+ public boolean hasPrevious() {
+ return i > 0;
+ }
+
+ public int nextIndex() {
+ return i;
+ }
+
+ public Object previous() {
+ if (!hasPrevious()) {
+ throw new NoSuchElementException();
+ }
+ return get(last = --i);
+ }
+
+ public int previousIndex() {
+ return i - 1;
+ }
+
+ public void set(Object o) {
+ if (last == -1) {
+ throw new IllegalStateException();
+ }
+ AbstractList.this.set(last, o);
+ }
+ }
public void add(int index, Object element) {
throw new UnsupportedOperationException("add");
@@ -131,6 +191,14 @@
return -1;
}
+ public ListIterator listIterator() {
+ return new ListIteratorImpl();
+ }
+
+ public ListIterator listIterator(int from) {
+ return new ListIteratorImpl(from);
+ }
+
public Object remove(int index) {
throw new UnsupportedOperationException("remove");
}
diff --git a/user/super/com/google/gwt/emul/java/util/List.java b/user/super/com/google/gwt/emul/java/util/List.java
index 7435136..edf0bd7 100644
--- a/user/super/com/google/gwt/emul/java/util/List.java
+++ b/user/super/com/google/gwt/emul/java/util/List.java
@@ -48,6 +48,10 @@
int lastIndexOf(Object o);
+ ListIterator listIterator();
+
+ ListIterator listIterator(int from);
+
Object remove(int index);
boolean remove(Object o);
diff --git a/user/super/com/google/gwt/emul/java/util/ListIterator.java b/user/super/com/google/gwt/emul/java/util/ListIterator.java
new file mode 100644
index 0000000..ad7d43c
--- /dev/null
+++ b/user/super/com/google/gwt/emul/java/util/ListIterator.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2006 Google Inc.
+ *
+ * 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 java.util;
+
+/**
+ * Uses Java 1.4 ListIterator for documentation. The methods hasNext, next, and
+ * remove are repeated to allow the specialized ListIterator documentation to
+ * be associated with them.
+ */
+public interface ListIterator extends Iterator {
+ void add(Object o);
+
+ boolean hasNext();
+
+ boolean hasPrevious();
+
+ Object next();
+
+ int nextIndex();
+
+ Object previous();
+
+ int previousIndex();
+
+ void remove();
+
+ void set(Object o);
+}
diff --git a/user/test/com/google/gwt/emultest/java/util/ArrayListTest.java b/user/test/com/google/gwt/emultest/java/util/ArrayListTest.java
index 328456d..8672a86 100644
--- a/user/test/com/google/gwt/emultest/java/util/ArrayListTest.java
+++ b/user/test/com/google/gwt/emultest/java/util/ArrayListTest.java
@@ -22,6 +22,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.ListIterator;
/** Tests ArrayList, and, by extension AbstractList. Uses inheritance to
* inherit all of Apache's TestList and TestCollection. */
@@ -29,17 +30,84 @@
public ArrayListTest() {
}
- protected List makeEmptyList() {
- return new ArrayList();
- }
-
public void testAddWatch() {
ArrayList s = new ArrayList();
s.add("watch");
assertEquals(s.get(0), "watch");
}
+ public void testListIteratorAddInSeveralPositions() {
+ ArrayList l = new ArrayList();
+ ListIterator i = l.listIterator();
+ l.add(new Integer(0));
+ for (int n = 2; n < 5; n += 2) {
+ l.add(new Integer(n));
+ }
+ i = l.listIterator();
+ i.next();
+ i.add(new Integer(1));
+ i.next();
+ i.next();
+ i.previous();
+ i.add(new Integer(3));
+ i.next();
+ i.add(new Integer(5));
+ i.add(new Integer(6));
+ for (int n = 0; n < 6; n++) {
+ assertEquals(new Integer(n), l.get(n));
+ }
+ }
+ public void testListIteratorCreateInvalid() {
+ ArrayList l = new ArrayList();
+ l.add(new Integer(1));
+ ListIterator i = l.listIterator(0);
+ try {
+ i = l.listIterator(1);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ i = l.listIterator(-1);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testListIteratorHasNextHasPreviousAndIndexes() {
+ List l = new ArrayList();
+ ListIterator i = l.listIterator();
+ assertFalse(i.hasNext());
+ assertFalse(i.hasPrevious());
+ i.add(new Integer(1));
+ assertEquals(1,i.nextIndex());
+ assertEquals(0, i.previousIndex());
+ i = l.listIterator();
+ assertEquals(0,i.nextIndex());
+ assertEquals(-1, i.previousIndex());
+ assertTrue(i.hasNext());
+ assertFalse(i.hasPrevious());
+ i.next();
+ assertEquals(1,i.nextIndex());
+ assertEquals(0, i.previousIndex());
+ assertFalse(i.hasNext());
+ assertTrue(i.hasPrevious());
+ }
+
+ public void testListIteratorSetInSeveralPositions() {
+ ArrayList l = new ArrayList();
+ for (int n = 0; n < 5; n += 2) {
+ l.add(new Integer(n));
+ }
+ ListIterator i = l.listIterator();
+ for (int n = 0; n < 3; n++) {
+ l.set(n, new Integer(n));
+ }
+ for (int n = 0; n < 3; n++) {
+ assertEquals(new Integer(n), l.get(n));
+ }
+ }
+
public void testRemoveRange() {
if (GWT.isScript()) {
ArrayList l = new ArrayList();
@@ -49,6 +117,10 @@
verifyRemoveRangeWorks(l);
}
}
+
+ protected List makeEmptyList() {
+ return new ArrayList();
+ }
private native void verifyRemoveRangeWorks(ArrayList l) /*-{
var startIndex = l.@java.util.ArrayList::startIndex;
@@ -75,5 +147,4 @@
@junit.framework.Assert::fail(Ljava/lang/String;)("endIndex - 1 should be empty");
}
}-*/;
-
}
diff --git a/user/test/org/apache/commons/collections/AbstractTestListIterator.java b/user/test/org/apache/commons/collections/AbstractTestListIterator.java
new file mode 100755
index 0000000..24701f5
--- /dev/null
+++ b/user/test/org/apache/commons/collections/AbstractTestListIterator.java
@@ -0,0 +1,285 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You 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.
+ *
+ * THIS CODE HAS BEEN EXTENSIVELY HACKED BY GOOGLE TO WORK WITH GWT.
+ */
+package org.apache.commons.collections;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+
+/**
+ * Abstract class for testing the ListIterator interface.
+ * <p>
+ * This class provides a framework for testing an implementation of
+ * ListIterator. Concrete subclasses must provide the list iterator to be
+ * tested. They must also specify certain details of how the list iterator
+ * operates by overriding the supportsXxx() methods if necessary.
+ *
+ * @since Commons Collections 3.0
+ * @version $Revision$ $Date$
+ *
+ * @author Rodney Waldhoff
+ * @author Stephen Colebourne
+ */
+public abstract class AbstractTestListIterator extends TestIterator {
+
+ // -----------------------------------------------------------------------
+ /**
+ * Implement this method to return a list iterator over an empty collection.
+ *
+ * @return an empty iterator
+ */
+ public abstract ListIterator makeEmptyListIterator();
+
+ /**
+ * Implement this method to return a list iterator over a collection with
+ * elements.
+ *
+ * @return a full iterator
+ */
+ public abstract ListIterator makeFullListIterator();
+
+ /**
+ * Implements the abstract superclass method to return the list iterator.
+ *
+ * @return an empty iterator
+ */
+ public Iterator makeEmptyIterator() {
+ return makeEmptyListIterator();
+ }
+
+ /**
+ * Implements the abstract superclass method to return the list iterator.
+ *
+ * @return a full iterator
+ */
+ public Iterator makeFullIterator() {
+ return makeFullListIterator();
+ }
+
+ /**
+ * Whether or not we are testing an iterator that supports add(). Default is
+ * true.
+ *
+ * @return true if Iterator supports add
+ */
+ public boolean supportsAdd() {
+ return true;
+ }
+
+ /**
+ * Whether or not we are testing an iterator that supports set(). Default is
+ * true.
+ *
+ * @return true if Iterator supports set
+ */
+ public boolean supportsSet() {
+ return true;
+ }
+
+ /**
+ * The value to be used in the add and set tests. Default is null.
+ */
+ public Object addSetValue() {
+ return null;
+ }
+
+ // -----------------------------------------------------------------------
+ /**
+ * Test that the empty list iterator contract is correct.
+ */
+ public void testEmptyListIteratorIsIndeedEmpty() {
+ if (supportsEmptyIterator() == false) {
+ return;
+ }
+
+ ListIterator it = makeEmptyListIterator();
+
+ assertEquals(false, it.hasNext());
+ assertEquals(0, it.nextIndex());
+ assertEquals(false, it.hasPrevious());
+ assertEquals(-1, it.previousIndex());
+
+ // next() should throw a NoSuchElementException
+ try {
+ it.next();
+ fail("NoSuchElementException must be thrown from empty ListIterator");
+ } catch (NoSuchElementException e) {
+ }
+
+ // previous() should throw a NoSuchElementException
+ try {
+ it.previous();
+ fail("NoSuchElementException must be thrown from empty ListIterator");
+ } catch (NoSuchElementException e) {
+ }
+ }
+
+ /**
+ * Test navigation through the iterator.
+ */
+ public void testWalkForwardAndBack() {
+ ArrayList list = new ArrayList();
+ ListIterator it = makeFullListIterator();
+ while (it.hasNext()) {
+ list.add(it.next());
+ }
+
+ // check state at end
+ assertEquals(false, it.hasNext());
+ assertEquals(true, it.hasPrevious());
+ try {
+ it.next();
+ fail("NoSuchElementException must be thrown from next at end of ListIterator");
+ } catch (NoSuchElementException e) {
+ }
+
+ // loop back through comparing
+ for (int i = list.size() - 1; i >= 0; i--) {
+ assertEquals(i + 1, it.nextIndex());
+ assertEquals(i, it.previousIndex());
+
+ Object obj = list.get(i);
+ assertEquals(obj, it.previous());
+ }
+
+ // check state at start
+ assertEquals(true, it.hasNext());
+ assertEquals(false, it.hasPrevious());
+ try {
+ it.previous();
+ fail("NoSuchElementException must be thrown from previous at start of ListIterator");
+ } catch (NoSuchElementException e) {
+ }
+ }
+
+ /**
+ * Test add behaviour.
+ */
+ public void testAdd() {
+ ListIterator it = makeFullListIterator();
+
+ Object addValue = addSetValue();
+ if (supportsAdd() == false) {
+ // check for UnsupportedOperationException if not supported
+ try {
+ it.add(addValue);
+ } catch (UnsupportedOperationException ex) {
+ }
+ return;
+ }
+
+ // add at start should be OK, added should be previous
+ it = makeFullListIterator();
+ it.add(addValue);
+ assertEquals(addValue, it.previous());
+
+ // add at start should be OK, added should not be next
+ it = makeFullListIterator();
+ it.add(addValue);
+ assertTrue(addValue != it.next());
+
+ // add in middle and at end should be OK
+ it = makeFullListIterator();
+ while (it.hasNext()) {
+ it.next();
+ it.add(addValue);
+ // check add OK
+ assertEquals(addValue, it.previous());
+ it.next();
+ }
+ }
+
+ /**
+ * Test set behaviour.
+ */
+ public void testSet() {
+ ListIterator it = makeFullListIterator();
+
+ if (supportsSet() == false) {
+ // check for UnsupportedOperationException if not supported
+ try {
+ it.set(addSetValue());
+ } catch (UnsupportedOperationException ex) {
+ }
+ return;
+ }
+
+ // should throw IllegalStateException before next() called
+ try {
+ it.set(addSetValue());
+ fail();
+ } catch (IllegalStateException ex) {
+ }
+
+ // set after next should be fine
+ it.next();
+ it.set(addSetValue());
+
+ // repeated set calls should be fine
+ it.set(addSetValue());
+
+ }
+
+ public void testRemoveThenSet() {
+ ListIterator it = makeFullListIterator();
+ if (supportsRemove() && supportsSet()) {
+ it.next();
+ it.remove();
+ try {
+ it.set(addSetValue());
+ fail("IllegalStateException must be thrown from set after remove");
+ } catch (IllegalStateException e) {
+ }
+ }
+ }
+
+ public void testAddThenSet() {
+ ListIterator it = makeFullListIterator();
+ // add then set
+ if (supportsAdd() && supportsSet()) {
+ it.next();
+ it.add(addSetValue());
+ try {
+ it.set(addSetValue());
+ fail("IllegalStateException must be thrown from set after add");
+ } catch (IllegalStateException e) {
+ }
+ }
+ }
+
+ /**
+ * Test remove after add behaviour.
+ */
+ public void testAddThenRemove() {
+ ListIterator it = makeFullListIterator();
+
+ // add then remove
+ if (supportsAdd() && supportsRemove()) {
+ it.next();
+ it.add(addSetValue());
+ try {
+ it.remove();
+ fail("IllegalStateException must be thrown from remove after add");
+ } catch (IllegalStateException e) {
+ }
+ }
+ }
+
+}
diff --git a/user/test/org/apache/commons/collections/TestIterator.java b/user/test/org/apache/commons/collections/TestIterator.java
index fcb94d6..9b779da 100644
--- a/user/test/org/apache/commons/collections/TestIterator.java
+++ b/user/test/org/apache/commons/collections/TestIterator.java
@@ -52,6 +52,16 @@
}
/**
+ * Whether or not we are testing an iterator that supports remove.
+ * Default is true.
+ *
+ * @return true if Iterators can remove elements
+ */
+ public boolean supportsRemove() {
+ return true;
+ }
+
+ /**
* Should throw a NoSuchElementException.
*/
public void testEmptyIterator() {
diff --git a/user/test/org/apache/commons/collections/TestList.java b/user/test/org/apache/commons/collections/TestList.java
index 40e294c..9a0135b 100644
--- a/user/test/org/apache/commons/collections/TestList.java
+++ b/user/test/org/apache/commons/collections/TestList.java
@@ -22,6 +22,8 @@
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
/**
@@ -84,6 +86,28 @@
}
+
+ /**
+ * Whether or not we are testing an iterator that can be
+ * empty. Default is true.
+ *
+ * @return true if Iterators can be empty
+ */
+ public boolean supportsEmptyIterator() {
+ return true;
+ }
+
+ /**
+ * Whether or not we are testing an list that allows
+ * element set. Default is true.
+ *
+ * @return true if Lists support element set
+ */
+ public boolean isSetSupported() {
+ return true;
+ }
+
+
/**
* Returns the {@link collection} field cast to a {@link List}.
*
@@ -106,7 +130,315 @@
+ public class TestListIterator extends AbstractTestListIterator {
+ public Object addSetValue() {
+ return TestList.this.getOtherElements()[0];
+ }
+
+ public boolean supportsRemove() {
+ return TestList.this.isRemoveSupported();
+ }
+
+ public boolean supportsAdd() {
+ return TestList.this.isAddSupported();
+ }
+
+ public boolean supportsSet() {
+ return TestList.this.isSetSupported();
+ }
+
+ public ListIterator makeEmptyListIterator() {
+ resetEmpty();
+ return ((List) TestList.this.collection).listIterator();
+ }
+
+ public ListIterator makeFullListIterator() {
+ resetFull();
+ return ((List) TestList.this.collection).listIterator();
+ }
+
+ public Object makeObject() {
+ return ((List) TestList.this.collection).listIterator();
+ }
+ }
+
+ /**
+ * Tests the read-only bits of {@link List#listIterator()}.
+ */
+ public void testListListIterator() {
+ resetFull();
+ forwardTest(getList().listIterator(), 0);
+ backwardTest(getList().listIterator(), 0);
+ }
+
+ /**
+ * Tests the read-only bits of {@link List#listIterator(int)}.
+ */
+ public void testListListIteratorByIndex() {
+ resetFull();
+ try {
+ getList().listIterator(-1);
+ } catch (IndexOutOfBoundsException ex) {
+ }
+ resetFull();
+ try {
+ getList().listIterator(getList().size() + 1);
+ } catch (IndexOutOfBoundsException ex) {
+ }
+ resetFull();
+ for (int i = 0; i <= confirmed.size(); i++) {
+ forwardTest(getList().listIterator(i), i);
+ backwardTest(getList().listIterator(i), i);
+ }
+ resetFull();
+ for (int i = 0; i <= confirmed.size(); i++) {
+ backwardTest(getList().listIterator(i), i);
+ }
+ }
+
+ // -----------------------------------------------------------------------
+ /**
+ * Tests remove on list iterator is correct.
+ */
+ public void testListListIteratorPreviousRemoveNext() {
+ if (isRemoveSupported() == false)
+ return;
+ resetFull();
+ if (collection.size() < 4)
+ return;
+ ListIterator it = getList().listIterator();
+ Object zero = it.next();
+ Object one = it.next();
+ Object two = it.next();
+ Object two2 = it.previous();
+ Object one2 = it.previous();
+ assertEquals(one, one2);
+ assertEquals(two, two2);
+ assertEquals(zero, getList().get(0));
+ assertEquals(one, getList().get(1));
+ assertEquals(two, getList().get(2));
+
+ it.remove(); // removed element at index 1 (one)
+ assertEquals(zero, getList().get(0));
+ assertEquals(two, getList().get(1));
+ Object two3 = it.next(); // do next after remove
+ assertEquals(two, two3);
+ assertEquals(collection.size() > 2, it.hasNext());
+ assertEquals(true, it.hasPrevious());
+ }
+
+ /**
+ * Tests remove on list iterator is correct.
+ */
+ public void testListListIteratorPreviousRemovePrevious() {
+ if (isRemoveSupported() == false)
+ return;
+ resetFull();
+ if (collection.size() < 4)
+ return;
+ ListIterator it = getList().listIterator();
+ Object zero = it.next();
+ Object one = it.next();
+ Object two = it.next();
+ Object two2 = it.previous();
+ Object one2 = it.previous();
+ assertEquals(one, one2);
+ assertEquals(two, two2);
+ assertEquals(zero, getList().get(0));
+ assertEquals(one, getList().get(1));
+ assertEquals(two, getList().get(2));
+
+ it.remove(); // removed element at index 1 (one)
+ assertEquals(zero, getList().get(0));
+ assertEquals(two, getList().get(1));
+ Object zero3 = it.previous(); // do previous after remove
+ assertEquals(zero, zero3);
+ assertEquals(false, it.hasPrevious());
+ assertEquals(collection.size() > 2, it.hasNext());
+ }
+
+ /**
+ * Tests remove on list iterator is correct.
+ */
+ public void testListListIteratorNextRemoveNext() {
+ if (isRemoveSupported() == false)
+ return;
+ resetFull();
+ if (collection.size() < 4)
+ return;
+ ListIterator it = getList().listIterator();
+ Object zero = it.next();
+ Object one = it.next();
+ Object two = it.next();
+ assertEquals(zero, getList().get(0));
+ assertEquals(one, getList().get(1));
+ assertEquals(two, getList().get(2));
+ Object three = getList().get(3);
+
+ it.remove(); // removed element at index 2 (two)
+ assertEquals(zero, getList().get(0));
+ assertEquals(one, getList().get(1));
+ Object three2 = it.next(); // do next after remove
+ assertEquals(three, three2);
+ assertEquals(collection.size() > 3, it.hasNext());
+ assertEquals(true, it.hasPrevious());
+ }
+
+ /**
+ * Tests remove on list iterator is correct.
+ */
+ public void testListListIteratorNextRemovePrevious() {
+ if (isRemoveSupported() == false)
+ return;
+ resetFull();
+ if (collection.size() < 4)
+ return;
+ ListIterator it = getList().listIterator();
+ Object zero = it.next();
+ Object one = it.next();
+ Object two = it.next();
+ assertEquals(zero, getList().get(0));
+ assertEquals(one, getList().get(1));
+ assertEquals(two, getList().get(2));
+
+ it.remove(); // removed element at index 2 (two)
+ assertEquals(zero, getList().get(0));
+ assertEquals(one, getList().get(1));
+ Object one2 = it.previous(); // do previous after remove
+ assertEquals(one, one2);
+ assertEquals(true, it.hasNext());
+ assertEquals(true, it.hasPrevious());
+ }
+
+ // -----------------------------------------------------------------------
+ /**
+ * Traverses to the end of the given iterator.
+ *
+ * @param iter the iterator to traverse
+ * @param i the starting index
+ */
+ private void forwardTest(ListIterator iter, int i) {
+ List list = getList();
+ int max = getFullElements().length;
+
+ while (i < max) {
+ assertTrue("Iterator should have next", iter.hasNext());
+ assertEquals("Iterator.nextIndex should work", iter.nextIndex(), i);
+ assertEquals("Iterator.previousIndex should work", iter.previousIndex(),
+ i - 1);
+ Object o = iter.next();
+ assertEquals("Iterator returned correct element f", list.get(i), o);
+ i++;
+ }
+
+ assertTrue("Iterator shouldn't have next", !iter.hasNext());
+ assertEquals("nextIndex should be size", iter.nextIndex(), max);
+ assertEquals("previousIndex should be size - 1", iter.previousIndex(),
+ max - 1);
+
+ try {
+ iter.next();
+ fail("Exhausted iterator should raise NoSuchElement");
+ } catch (NoSuchElementException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Traverses to the beginning of the given iterator.
+ *
+ * @param iter the iterator to traverse
+ * @param i the starting index
+ */
+ private void backwardTest(ListIterator iter, int i) {
+ List list = getList();
+
+ while (i > 0) {
+ assertTrue("Iterator should have previous, i:" + i, iter.hasPrevious());
+ assertEquals("Iterator.nextIndex should work, i:" + i, iter.nextIndex(),
+ i);
+ assertEquals("Iterator.previousIndex should work, i:" + i,
+ iter.previousIndex(), i - 1);
+ Object o = iter.previous();
+ assertEquals("Iterator returned correct element b", list.get(i - 1), o);
+ i--;
+ }
+
+ assertTrue("Iterator shouldn't have previous", !iter.hasPrevious());
+ int nextIndex = iter.nextIndex();
+ assertEquals("nextIndex should be 0, actual value: " + nextIndex,
+ nextIndex, 0);
+ int prevIndex = iter.previousIndex();
+ assertEquals("previousIndex should be -1, actual value: " + prevIndex,
+ prevIndex, -1);
+
+ try {
+ iter.previous();
+ fail("Exhausted iterator should raise NoSuchElement");
+ } catch (NoSuchElementException e) {
+ // expected
+ }
+
+ }
+
+ /**
+ * Tests the {@link ListIterator#add(Object)} method of the list iterator.
+ */
+ public void testListIteratorAdd() {
+ if (!isAddSupported())
+ return;
+
+ resetEmpty();
+ List list1 = getList();
+ List list2 = getConfirmedList();
+
+ Object[] elements = getFullElements();
+ ListIterator iter1 = list1.listIterator();
+ ListIterator iter2 = list2.listIterator();
+
+ for (int i = 0; i < elements.length; i++) {
+ iter1.add(elements[i]);
+ iter2.add(elements[i]);
+ verify();
+ }
+
+ resetFull();
+ iter1 = getList().listIterator();
+ iter2 = getConfirmedList().listIterator();
+ for (int i = 0; i < elements.length; i++) {
+ iter1.next();
+ iter2.next();
+ iter1.add(elements[i]);
+ iter2.add(elements[i]);
+ verify();
+ }
+ }
+
+ /**
+ * Tests the {@link ListIterator#set(Object)} method of the list iterator.
+ */
+ public void testListIteratorSet() {
+ if (!isSetSupported())
+ return;
+
+ Object[] elements = getFullElements();
+
+ resetFull();
+ ListIterator iter1 = getList().listIterator();
+ ListIterator iter2 = getConfirmedList().listIterator();
+ for (int i = 0; i < elements.length; i++) {
+ iter1.next();
+ iter2.next();
+ iter1.set(elements[i]);
+ iter2.set(elements[i]);
+ verify();
+ }
+ }
+
+
+
+
/**
* Tests {@link List#add(int,Object)}.
*/