001: /*
002: * Copyright 1999-2004 The Apache Software Foundation
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.commons.collections;
017:
018: import java.util.AbstractCollection;
019: import java.util.ArrayList;
020: import java.util.Arrays;
021: import java.util.Collection;
022: import java.util.Collections;
023: import java.util.Iterator;
024: import java.util.List;
025: import java.util.ListIterator;
026: import java.util.NoSuchElementException;
027:
028: /**
029: * Tests base {@link java.util.List} methods and contracts.
030: * <p>
031: * To use, simply extend this class, and implement
032: * the {@link #makeList} method.
033: * <p>
034: * If your {@link List} fails one of these tests by design,
035: * you may still use this base set of cases. Simply override the
036: * test case (method) your {@link List} fails.
037: *
038: * @author Rodney Waldhoff
039: * @author Paul Jack
040: * @version $Id: TestList.java,v 1.13.2.1 2004/05/22 12:14:05 scolebourne Exp $
041: */
042: public abstract class TestList extends TestCollection {
043:
044: /**
045: * Return a new, empty {@link List} to be used for testing.
046: *
047: * @return an empty list for testing.
048: */
049: protected abstract List makeEmptyList();
050:
051: /**
052: * Return a new, full {@link List} to be used for testing.
053: *
054: * @return a full list for testing
055: */
056: protected List makeFullList() {
057: // only works if list supports optional "addAll(Collection)"
058: List list = makeEmptyList();
059: list.addAll(Arrays.asList(getFullElements()));
060: return list;
061: }
062:
063: /**
064: * Returns {@link makeEmptyList()}.
065: *
066: * @return an empty list to be used for testing
067: */
068: final protected Collection makeCollection() {
069: return makeEmptyList();
070: }
071:
072: /**
073: * Returns {@link makeFullList()}.
074: *
075: * @return a full list to be used for testing
076: */
077: final protected Collection makeFullCollection() {
078: return makeFullList();
079: }
080:
081: /**
082: * Whether or not we are testing an iterator that can be
083: * empty. Default is true.
084: *
085: * @return true if Iterators can be empty
086: */
087: public boolean supportsEmptyIterator() {
088: return true;
089: }
090:
091: /**
092: * Whether or not we are testing an list that allows
093: * element set. Default is true.
094: *
095: * @return true if Lists support element set
096: */
097: public boolean isSetSupported() {
098: return true;
099: }
100:
101: /**
102: * Returns the {@link collection} field cast to a {@link List}.
103: *
104: * @return the collection field as a List
105: */
106: protected List getList() {
107: return (List) collection;
108: }
109:
110: /**
111: * Returns the {@link confirmed} field cast to a {@link List}.
112: *
113: * @return the confirmed field as a List
114: */
115: protected List getConfirmedList() {
116: return (List) confirmed;
117: }
118:
119: public class TestListIterator extends AbstractTestListIterator {
120:
121: public Object addSetValue() {
122: return TestList.this .getOtherElements()[0];
123: }
124:
125: public boolean supportsRemove() {
126: return TestList.this .isRemoveSupported();
127: }
128:
129: public boolean supportsAdd() {
130: return TestList.this .isAddSupported();
131: }
132:
133: public boolean supportsSet() {
134: return TestList.this .isSetSupported();
135: }
136:
137: public ListIterator makeEmptyListIterator() {
138: resetEmpty();
139: return ((List) TestList.this .collection).listIterator();
140: }
141:
142: public ListIterator makeFullListIterator() {
143: resetFull();
144: return ((List) TestList.this .collection).listIterator();
145: }
146:
147: public Object makeObject() {
148: return ((List) TestList.this .collection).listIterator();
149: }
150: }
151:
152: /**
153: * Tests the read-only bits of {@link List#listIterator()}.
154: */
155: public void testListListIterator() {
156: resetFull();
157: forwardTest(getList().listIterator(), 0);
158: backwardTest(getList().listIterator(), 0);
159: }
160:
161: /**
162: * Tests the read-only bits of {@link List#listIterator(int)}.
163: */
164: public void testListListIteratorByIndex() {
165: resetFull();
166: try {
167: getList().listIterator(-1);
168: } catch (IndexOutOfBoundsException ex) {
169: }
170: resetFull();
171: try {
172: getList().listIterator(getList().size() + 1);
173: } catch (IndexOutOfBoundsException ex) {
174: }
175: resetFull();
176: for (int i = 0; i <= confirmed.size(); i++) {
177: forwardTest(getList().listIterator(i), i);
178: backwardTest(getList().listIterator(i), i);
179: }
180: resetFull();
181: for (int i = 0; i <= confirmed.size(); i++) {
182: backwardTest(getList().listIterator(i), i);
183: }
184: }
185:
186: // -----------------------------------------------------------------------
187: /**
188: * Tests remove on list iterator is correct.
189: */
190: public void testListListIteratorPreviousRemoveNext() {
191: if (isRemoveSupported() == false)
192: return;
193: resetFull();
194: if (collection.size() < 4)
195: return;
196: ListIterator it = getList().listIterator();
197: Object zero = it.next();
198: Object one = it.next();
199: Object two = it.next();
200: Object two2 = it.previous();
201: Object one2 = it.previous();
202: assertEquals(one, one2);
203: assertEquals(two, two2);
204: assertEquals(zero, getList().get(0));
205: assertEquals(one, getList().get(1));
206: assertEquals(two, getList().get(2));
207:
208: it.remove(); // removed element at index 1 (one)
209: assertEquals(zero, getList().get(0));
210: assertEquals(two, getList().get(1));
211: Object two3 = it.next(); // do next after remove
212: assertEquals(two, two3);
213: assertEquals(collection.size() > 2, it.hasNext());
214: assertEquals(true, it.hasPrevious());
215: }
216:
217: /**
218: * Tests remove on list iterator is correct.
219: */
220: public void testListListIteratorPreviousRemovePrevious() {
221: if (isRemoveSupported() == false)
222: return;
223: resetFull();
224: if (collection.size() < 4)
225: return;
226: ListIterator it = getList().listIterator();
227: Object zero = it.next();
228: Object one = it.next();
229: Object two = it.next();
230: Object two2 = it.previous();
231: Object one2 = it.previous();
232: assertEquals(one, one2);
233: assertEquals(two, two2);
234: assertEquals(zero, getList().get(0));
235: assertEquals(one, getList().get(1));
236: assertEquals(two, getList().get(2));
237:
238: it.remove(); // removed element at index 1 (one)
239: assertEquals(zero, getList().get(0));
240: assertEquals(two, getList().get(1));
241: Object zero3 = it.previous(); // do previous after remove
242: assertEquals(zero, zero3);
243: assertEquals(false, it.hasPrevious());
244: assertEquals(collection.size() > 2, it.hasNext());
245: }
246:
247: /**
248: * Tests remove on list iterator is correct.
249: */
250: public void testListListIteratorNextRemoveNext() {
251: if (isRemoveSupported() == false)
252: return;
253: resetFull();
254: if (collection.size() < 4)
255: return;
256: ListIterator it = getList().listIterator();
257: Object zero = it.next();
258: Object one = it.next();
259: Object two = it.next();
260: assertEquals(zero, getList().get(0));
261: assertEquals(one, getList().get(1));
262: assertEquals(two, getList().get(2));
263: Object three = getList().get(3);
264:
265: it.remove(); // removed element at index 2 (two)
266: assertEquals(zero, getList().get(0));
267: assertEquals(one, getList().get(1));
268: Object three2 = it.next(); // do next after remove
269: assertEquals(three, three2);
270: assertEquals(collection.size() > 3, it.hasNext());
271: assertEquals(true, it.hasPrevious());
272: }
273:
274: /**
275: * Tests remove on list iterator is correct.
276: */
277: public void testListListIteratorNextRemovePrevious() {
278: if (isRemoveSupported() == false)
279: return;
280: resetFull();
281: if (collection.size() < 4)
282: return;
283: ListIterator it = getList().listIterator();
284: Object zero = it.next();
285: Object one = it.next();
286: Object two = it.next();
287: assertEquals(zero, getList().get(0));
288: assertEquals(one, getList().get(1));
289: assertEquals(two, getList().get(2));
290:
291: it.remove(); // removed element at index 2 (two)
292: assertEquals(zero, getList().get(0));
293: assertEquals(one, getList().get(1));
294: Object one2 = it.previous(); // do previous after remove
295: assertEquals(one, one2);
296: assertEquals(true, it.hasNext());
297: assertEquals(true, it.hasPrevious());
298: }
299:
300: // -----------------------------------------------------------------------
301: /**
302: * Traverses to the end of the given iterator.
303: *
304: * @param iter the iterator to traverse
305: * @param i the starting index
306: */
307: private void forwardTest(ListIterator iter, int i) {
308: List list = getList();
309: int max = getFullElements().length;
310:
311: while (i < max) {
312: assertTrue("Iterator should have next", iter.hasNext());
313: assertEquals("Iterator.nextIndex should work", iter
314: .nextIndex(), i);
315: assertEquals("Iterator.previousIndex should work", iter
316: .previousIndex(), i - 1);
317: Object o = iter.next();
318: assertEquals("Iterator returned correct element f", list
319: .get(i), o);
320: i++;
321: }
322:
323: assertTrue("Iterator shouldn't have next", !iter.hasNext());
324: assertEquals("nextIndex should be size", iter.nextIndex(), max);
325: assertEquals("previousIndex should be size - 1", iter
326: .previousIndex(), max - 1);
327:
328: try {
329: iter.next();
330: fail("Exhausted iterator should raise NoSuchElement");
331: } catch (NoSuchElementException e) {
332: // expected
333: }
334: }
335:
336: /**
337: * Traverses to the beginning of the given iterator.
338: *
339: * @param iter the iterator to traverse
340: * @param i the starting index
341: */
342: private void backwardTest(ListIterator iter, int i) {
343: List list = getList();
344:
345: while (i > 0) {
346: assertTrue("Iterator should have previous, i:" + i, iter
347: .hasPrevious());
348: assertEquals("Iterator.nextIndex should work, i:" + i, iter
349: .nextIndex(), i);
350: assertEquals("Iterator.previousIndex should work, i:" + i,
351: iter.previousIndex(), i - 1);
352: Object o = iter.previous();
353: assertEquals("Iterator returned correct element b", list
354: .get(i - 1), o);
355: i--;
356: }
357:
358: assertTrue("Iterator shouldn't have previous", !iter
359: .hasPrevious());
360: int nextIndex = iter.nextIndex();
361: assertEquals("nextIndex should be 0, actual value: "
362: + nextIndex, nextIndex, 0);
363: int prevIndex = iter.previousIndex();
364: assertEquals("previousIndex should be -1, actual value: "
365: + prevIndex, prevIndex, -1);
366:
367: try {
368: iter.previous();
369: fail("Exhausted iterator should raise NoSuchElement");
370: } catch (NoSuchElementException e) {
371: // expected
372: }
373:
374: }
375:
376: /**
377: * Tests the {@link ListIterator#add(Object)} method of the list iterator.
378: */
379: public void testListIteratorAdd() {
380: if (!isAddSupported())
381: return;
382:
383: resetEmpty();
384: List list1 = getList();
385: List list2 = getConfirmedList();
386:
387: Object[] elements = getFullElements();
388: ListIterator iter1 = list1.listIterator();
389: ListIterator iter2 = list2.listIterator();
390:
391: for (int i = 0; i < elements.length; i++) {
392: iter1.add(elements[i]);
393: iter2.add(elements[i]);
394: verify();
395: }
396:
397: resetFull();
398: iter1 = getList().listIterator();
399: iter2 = getConfirmedList().listIterator();
400: for (int i = 0; i < elements.length; i++) {
401: iter1.next();
402: iter2.next();
403: iter1.add(elements[i]);
404: iter2.add(elements[i]);
405: verify();
406: }
407: }
408:
409: /**
410: * Tests the {@link ListIterator#set(Object)} method of the list iterator.
411: */
412: public void testListIteratorSet() {
413: if (!isSetSupported())
414: return;
415:
416: Object[] elements = getFullElements();
417:
418: resetFull();
419: ListIterator iter1 = getList().listIterator();
420: ListIterator iter2 = getConfirmedList().listIterator();
421: for (int i = 0; i < elements.length; i++) {
422: iter1.next();
423: iter2.next();
424: iter1.set(elements[i]);
425: iter2.set(elements[i]);
426: verify();
427: }
428: }
429:
430: /**
431: * Tests {@link List#add(int,Object)}.
432: */
433: public void testListAddByIndex() {
434: if (!isAddSupported())
435: return;
436:
437: Object element = getOtherElements()[0];
438: int max = getFullElements().length;
439:
440: for (int i = 0; i <= max; i++) {
441: resetFull();
442: ((List) collection).add(i, element);
443: ((List) confirmed).add(i, element);
444: verify();
445: }
446: }
447:
448: /**
449: * Tests {@link List#equals(Object)}.
450: */
451: public void testListEquals() {
452: resetEmpty();
453: List list = getList();
454: assertTrue("Empty lists should be equal", list
455: .equals(confirmed));
456: verify();
457: assertTrue("Empty list should equal self", list.equals(list));
458: verify();
459:
460: List list2 = Arrays.asList(getFullElements());
461: assertTrue("Empty list shouldn't equal full", !list
462: .equals(list2));
463: verify();
464:
465: list2 = Arrays.asList(getOtherElements());
466: assertTrue("Empty list shouldn't equal other", !list
467: .equals(list2));
468: verify();
469:
470: resetFull();
471: list = getList();
472: assertTrue("Full lists should be equal", list.equals(confirmed));
473: verify();
474: assertTrue("Full list should equal self", list.equals(list));
475: verify();
476:
477: list2 = makeEmptyList();
478: assertTrue("Full list shouldn't equal empty", !list
479: .equals(list2));
480: verify();
481:
482: list2 = Arrays.asList(getOtherElements());
483: assertTrue("Full list shouldn't equal other", !list
484: .equals(list2));
485: verify();
486:
487: list2 = Arrays.asList(getFullElements());
488: Collections.reverse(list2);
489: assertTrue(
490: "Full list shouldn't equal full list with same elements"
491: + " but different order", !list.equals(list2));
492: verify();
493:
494: assertTrue("List shouldn't equal String", !list.equals(""));
495: verify();
496:
497: final List listForC = Arrays.asList(getFullElements());
498: Collection c = new AbstractCollection() {
499: public int size() {
500: return listForC.size();
501: }
502:
503: public Iterator iterator() {
504: return listForC.iterator();
505: }
506: };
507:
508: assertTrue("List shouldn't equal nonlist with same elements "
509: + " in same order", !list.equals(c));
510: verify();
511: }
512:
513: /**
514: * Tests {@link List#hashCode()}.
515: */
516: public void testListHashCode() {
517: resetEmpty();
518: int hash1 = collection.hashCode();
519: int hash2 = confirmed.hashCode();
520: assertEquals("Empty lists should have equal hashCodes", hash1,
521: hash2);
522: verify();
523:
524: resetFull();
525: hash1 = collection.hashCode();
526: hash2 = confirmed.hashCode();
527: assertEquals("Full lists should have equal hashCodes", hash1,
528: hash2);
529: verify();
530: }
531:
532: /**
533: * Tests {@link List#get(int)}.
534: */
535: public void testListGetByIndex() {
536: resetFull();
537: List list = getList();
538: Object[] elements = getFullElements();
539: for (int i = 0; i < elements.length; i++) {
540: assertEquals("List should contain correct elements",
541: elements[i], list.get(i));
542: verify();
543: }
544: }
545:
546: /**
547: * Tests {@link List#indexOf()}.
548: */
549: public void testListIndexOf() {
550: resetFull();
551: List list1 = getList();
552: List list2 = getConfirmedList();
553:
554: Iterator iterator = list2.iterator();
555: while (iterator.hasNext()) {
556: Object element = iterator.next();
557: assertEquals("indexOf should return correct result", list1
558: .indexOf(element), list2.indexOf(element));
559: verify();
560: }
561:
562: Object[] other = getOtherElements();
563: for (int i = 0; i < other.length; i++) {
564: assertEquals(
565: "indexOf should return -1 for nonexistent element",
566: list1.indexOf(other[i]), -1);
567: verify();
568: }
569: }
570:
571: /**
572: * Tests {@link List#lastIndexOf()}.
573: */
574: public void testListLastIndexOf() {
575: resetFull();
576: List list1 = getList();
577: List list2 = getConfirmedList();
578:
579: Iterator iterator = list2.iterator();
580: while (iterator.hasNext()) {
581: Object element = iterator.next();
582: assertEquals("lastIndexOf should return correct result",
583: list1.lastIndexOf(element), list2
584: .lastIndexOf(element));
585: verify();
586: }
587:
588: Object[] other = getOtherElements();
589: for (int i = 0; i < other.length; i++) {
590: assertEquals(
591: "lastIndexOf should return -1 for nonexistent "
592: + "element", list1.lastIndexOf(other[i]),
593: -1);
594: verify();
595: }
596: }
597:
598: /**
599: * Tests {@link List#remove(int)}.
600: */
601: public void testListRemoveByIndex() {
602: if (!isRemoveSupported())
603: return;
604:
605: int max = getFullElements().length;
606: for (int i = 0; i < max; i++) {
607: resetFull();
608: Object o1 = ((List) collection).remove(i);
609: Object o2 = ((List) confirmed).remove(i);
610: assertEquals("remove should return correct element", o1, o2);
611: verify();
612: }
613: }
614:
615: /**
616: * Returns an empty {@link ArrayList}.
617: */
618: protected Collection makeConfirmedCollection() {
619: ArrayList list = new ArrayList();
620: return list;
621: }
622:
623: /**
624: * Returns a full {@link ArrayList}.
625: */
626: protected Collection makeConfirmedFullCollection() {
627: ArrayList list = new ArrayList();
628: list.addAll(Arrays.asList(getFullElements()));
629: return list;
630: }
631:
632: /**
633: * Verifies that the test list implementation matches the confirmed list
634: * implementation.
635: */
636: protected void verify() {
637: super .verify();
638:
639: List list1 = getList();
640: List list2 = getConfirmedList();
641:
642: assertEquals("List should equal confirmed", list1, list2);
643: assertEquals("Confirmed should equal list", list2, list1);
644:
645: assertEquals("Hash codes should be equal", list1.hashCode(),
646: list2.hashCode());
647:
648: int i = 0;
649: Iterator iterator1 = list1.iterator();
650: Iterator iterator2 = list2.iterator();
651: Object[] array = list1.toArray();
652: while (iterator2.hasNext()) {
653: assertTrue("List iterator should have next", iterator1
654: .hasNext());
655: Object o1 = iterator1.next();
656: Object o2 = iterator2.next();
657: assertEquals("Iterator elements should be equal", o1, o2);
658: o2 = list1.get(i);
659: assertEquals("get should return correct element", o1, o2);
660: o2 = array[i];
661: assertEquals("toArray should have correct element", o1, o2);
662: i++;
663: }
664: }
665:
666: }
|