001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with this
004: * work for additional information regarding copyright ownership. The ASF
005: * licenses this file to You under the Apache License, Version 2.0 (the
006: * "License"); you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
013: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
014: * License for the specific language governing permissions and limitations under
015: * the License.
016: *
017: * THIS CODE HAS BEEN EXTENSIVELY HACKED BY GOOGLE TO WORK WITH GWT.
018: */
019: package org.apache.commons.collections;
020:
021: import java.util.ArrayList;
022: import java.util.Iterator;
023: import java.util.ListIterator;
024: import java.util.NoSuchElementException;
025:
026: /**
027: * Abstract class for testing the ListIterator interface.
028: * <p>
029: * This class provides a framework for testing an implementation of
030: * ListIterator. Concrete subclasses must provide the list iterator to be
031: * tested. They must also specify certain details of how the list iterator
032: * operates by overriding the supportsXxx() methods if necessary.
033: *
034: * @since Commons Collections 3.0
035: * @version $Revision$ $Date$
036: *
037: * @author Rodney Waldhoff
038: * @author Stephen Colebourne
039: */
040: public abstract class AbstractTestListIterator extends TestIterator {
041:
042: // -----------------------------------------------------------------------
043: /**
044: * Implement this method to return a list iterator over an empty collection.
045: *
046: * @return an empty iterator
047: */
048: public abstract ListIterator makeEmptyListIterator();
049:
050: /**
051: * Implement this method to return a list iterator over a collection with
052: * elements.
053: *
054: * @return a full iterator
055: */
056: public abstract ListIterator makeFullListIterator();
057:
058: /**
059: * Implements the abstract superclass method to return the list iterator.
060: *
061: * @return an empty iterator
062: */
063: public Iterator makeEmptyIterator() {
064: return makeEmptyListIterator();
065: }
066:
067: /**
068: * Implements the abstract superclass method to return the list iterator.
069: *
070: * @return a full iterator
071: */
072: public Iterator makeFullIterator() {
073: return makeFullListIterator();
074: }
075:
076: /**
077: * Whether or not we are testing an iterator that supports add(). Default is
078: * true.
079: *
080: * @return true if Iterator supports add
081: */
082: public boolean supportsAdd() {
083: return true;
084: }
085:
086: /**
087: * Whether or not we are testing an iterator that supports set(). Default is
088: * true.
089: *
090: * @return true if Iterator supports set
091: */
092: public boolean supportsSet() {
093: return true;
094: }
095:
096: /**
097: * The value to be used in the add and set tests. Default is null.
098: */
099: public Object addSetValue() {
100: return null;
101: }
102:
103: // -----------------------------------------------------------------------
104: /**
105: * Test that the empty list iterator contract is correct.
106: */
107: public void testEmptyListIteratorIsIndeedEmpty() {
108: if (supportsEmptyIterator() == false) {
109: return;
110: }
111:
112: ListIterator it = makeEmptyListIterator();
113:
114: assertEquals(false, it.hasNext());
115: assertEquals(0, it.nextIndex());
116: assertEquals(false, it.hasPrevious());
117: assertEquals(-1, it.previousIndex());
118:
119: // next() should throw a NoSuchElementException
120: try {
121: it.next();
122: fail("NoSuchElementException must be thrown from empty ListIterator");
123: } catch (NoSuchElementException e) {
124: }
125:
126: // previous() should throw a NoSuchElementException
127: try {
128: it.previous();
129: fail("NoSuchElementException must be thrown from empty ListIterator");
130: } catch (NoSuchElementException e) {
131: }
132: }
133:
134: /**
135: * Test navigation through the iterator.
136: */
137: public void testWalkForwardAndBack() {
138: ArrayList list = new ArrayList();
139: ListIterator it = makeFullListIterator();
140: while (it.hasNext()) {
141: list.add(it.next());
142: }
143:
144: // check state at end
145: assertEquals(false, it.hasNext());
146: assertEquals(true, it.hasPrevious());
147: try {
148: it.next();
149: fail("NoSuchElementException must be thrown from next at end of ListIterator");
150: } catch (NoSuchElementException e) {
151: }
152:
153: // loop back through comparing
154: for (int i = list.size() - 1; i >= 0; i--) {
155: assertEquals(i + 1, it.nextIndex());
156: assertEquals(i, it.previousIndex());
157:
158: Object obj = list.get(i);
159: assertEquals(obj, it.previous());
160: }
161:
162: // check state at start
163: assertEquals(true, it.hasNext());
164: assertEquals(false, it.hasPrevious());
165: try {
166: it.previous();
167: fail("NoSuchElementException must be thrown from previous at start of ListIterator");
168: } catch (NoSuchElementException e) {
169: }
170: }
171:
172: /**
173: * Test add behaviour.
174: */
175: public void testAdd() {
176: ListIterator it = makeFullListIterator();
177:
178: Object addValue = addSetValue();
179: if (supportsAdd() == false) {
180: // check for UnsupportedOperationException if not supported
181: try {
182: it.add(addValue);
183: } catch (UnsupportedOperationException ex) {
184: }
185: return;
186: }
187:
188: // add at start should be OK, added should be previous
189: it = makeFullListIterator();
190: it.add(addValue);
191: assertEquals(addValue, it.previous());
192:
193: // add at start should be OK, added should not be next
194: it = makeFullListIterator();
195: it.add(addValue);
196: assertTrue(addValue != it.next());
197:
198: // add in middle and at end should be OK
199: it = makeFullListIterator();
200: while (it.hasNext()) {
201: it.next();
202: it.add(addValue);
203: // check add OK
204: assertEquals(addValue, it.previous());
205: it.next();
206: }
207: }
208:
209: /**
210: * Test set behaviour.
211: */
212: public void testSet() {
213: ListIterator it = makeFullListIterator();
214:
215: if (supportsSet() == false) {
216: // check for UnsupportedOperationException if not supported
217: try {
218: it.set(addSetValue());
219: } catch (UnsupportedOperationException ex) {
220: }
221: return;
222: }
223:
224: // should throw IllegalStateException before next() called
225: try {
226: it.set(addSetValue());
227: fail();
228: } catch (IllegalStateException ex) {
229: }
230:
231: // set after next should be fine
232: it.next();
233: it.set(addSetValue());
234:
235: // repeated set calls should be fine
236: it.set(addSetValue());
237:
238: }
239:
240: public void testRemoveThenSet() {
241: ListIterator it = makeFullListIterator();
242: if (supportsRemove() && supportsSet()) {
243: it.next();
244: it.remove();
245: try {
246: it.set(addSetValue());
247: fail("IllegalStateException must be thrown from set after remove");
248: } catch (IllegalStateException e) {
249: }
250: }
251: }
252:
253: public void testAddThenSet() {
254: ListIterator it = makeFullListIterator();
255: // add then set
256: if (supportsAdd() && supportsSet()) {
257: it.next();
258: it.add(addSetValue());
259: try {
260: it.set(addSetValue());
261: fail("IllegalStateException must be thrown from set after add");
262: } catch (IllegalStateException e) {
263: }
264: }
265: }
266:
267: /**
268: * Test remove after add behaviour.
269: */
270: public void testAddThenRemove() {
271: ListIterator it = makeFullListIterator();
272:
273: // add then remove
274: if (supportsAdd() && supportsRemove()) {
275: it.next();
276: it.add(addSetValue());
277: try {
278: it.remove();
279: fail("IllegalStateException must be thrown from remove after add");
280: } catch (IllegalStateException e) {
281: }
282: }
283: }
284:
285: }
|