/******************************************************************************
* Copyright (c) 2006, 2010 VMware Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
* is available at http://www.opensource.org/licenses/apache2.0.php.
* You may elect to redistribute this code under either of these licenses.
*
* Contributors:
* VMware Inc.
*****************************************************************************/
package org.eclipse.gemini.blueprint.internal.service.collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
import junit.framework.TestCase;
import org.eclipse.gemini.blueprint.service.importer.support.internal.collection.DynamicCollection;
/**
* Tests related to the dynamic collection iterator (consistency and dynamic
* nature).
*
* @author Costin Leau
*
*/
public class DynamicCollectionIteratorTest extends TestCase {
private Collection dynamicCollection;
private Iterator iter;
protected void setUp() throws Exception {
dynamicCollection = new DynamicCollection();
iter = dynamicCollection.iterator();
}
protected void tearDown() throws Exception {
dynamicCollection = null;
iter = null;
}
// iterating tests
public void testAddWhileIterating() throws Exception {
assertTrue(dynamicCollection.isEmpty());
assertFalse(iter.hasNext());
Object a = new Object();
dynamicCollection.add(a);
assertTrue(iter.hasNext());
assertSame(a, iter.next());
assertFalse(iter.hasNext());
}
public void testRemoveWhileIterating() throws Exception {
assertTrue(dynamicCollection.isEmpty());
assertFalse(iter.hasNext());
Object a = new Object();
Object b = new Object();
Object c = new Object();
dynamicCollection.add(a);
dynamicCollection.add(b);
dynamicCollection.add(c);
assertTrue(iter.hasNext());
assertSame(a, iter.next());
dynamicCollection.remove(b);
assertTrue(iter.hasNext());
assertSame(c, iter.next());
}
public void testRemovePreviouslyIteratedWhileIterating() throws Exception {
assertTrue(dynamicCollection.isEmpty());
assertFalse(iter.hasNext());
Object a = new Object();
Object b = new Object();
dynamicCollection.add(a);
dynamicCollection.add(b);
assertTrue(iter.hasNext());
assertSame(a, iter.next());
assertTrue(iter.hasNext());
dynamicCollection.remove(a);
// still have b
assertTrue(iter.hasNext());
assertSame(b, iter.next());
}
public void testRemoveUniteratedWhileIterating() throws Exception {
assertTrue(dynamicCollection.isEmpty());
assertFalse(iter.hasNext());
Object a = new Object();
Object b = new Object();
Object c = new Object();
dynamicCollection.add(a);
dynamicCollection.add(b);
dynamicCollection.add(c);
assertTrue(iter.hasNext());
assertSame(a, iter.next());
assertTrue(iter.hasNext());
dynamicCollection.remove(a);
// still have b
assertTrue(iter.hasNext());
dynamicCollection.remove(b);
// still have c
assertTrue(iter.hasNext());
assertSame(c, iter.next());
}
public void testIteratorRemove() throws Exception {
Object a = new Object();
Object b = new Object();
Object c = new Object();
dynamicCollection.add(a);
dynamicCollection.add(b);
dynamicCollection.add(c);
assertTrue(iter.hasNext());
try {
iter.remove();
fail("remove() can be called only after next()");
}
catch (IllegalStateException ex) {
// expected
}
assertSame(a, iter.next());
assertSame(b, iter.next());
// remove b
iter.remove();
assertEquals(2, dynamicCollection.size());
assertSame(c, iter.next());
// remove c
iter.remove();
assertEquals(1, dynamicCollection.size());
try {
iter.remove();
fail("remove() can be called only once for each next()");
}
catch (IllegalStateException ex) {
// expected
}
}
public void testRemoveAllWhileIterating() throws Exception {
Object a = new Object();
Object b = new Object();
Object c = new Object();
dynamicCollection.add(a);
dynamicCollection.add(b);
dynamicCollection.add(c);
Collection col = new ArrayList();
col.add(a);
col.add(c);
assertSame(a, iter.next());
// remove a and c
dynamicCollection.removeAll(col);
assertSame(b, iter.next());
assertFalse(iter.hasNext());
}
public void testAddAllWhileIterating() throws Exception {
Object a = new Object();
Object b = new Object();
Object c = new Object();
dynamicCollection.add(a);
Collection col = new ArrayList();
col.add(b);
col.add(c);
assertSame(a, iter.next());
assertFalse(iter.hasNext());
dynamicCollection.addAll(col);
assertTrue(iter.hasNext());
assertSame(b, iter.next());
assertSame(c, iter.next());
}
public void testRemoveObjectWhenTheCollectionContainsDuplicates() throws Exception {
Object a = new Object();
Object b = new Object();
Object c = new Object();
// create a|b|a|c|a|a
dynamicCollection.add(a);
dynamicCollection.add(b);
dynamicCollection.add(a);
dynamicCollection.add(c);
dynamicCollection.add(a);
dynamicCollection.add(a);
Iterator i1 = dynamicCollection.iterator();
assertSame(a, iter.next());
assertSame(b, iter.next());
assertSame(a, iter.next());
iter.remove();
assertSame(a, i1.next());
assertSame(b, i1.next());
assertSame(c, i1.next());
assertSame(a, i1.next());
assertSame(c, iter.next());
assertSame(a, iter.next());
assertSame(a, iter.next());
iter.remove();
assertFalse(i1.hasNext());
assertFalse(iter.hasNext());
}
public void testRemoveUnexistingObj() throws Exception {
Object a = new Object();
Object b = new Object();
dynamicCollection.add(a);
assertFalse(dynamicCollection.remove(b));
assertTrue(dynamicCollection.remove(a));
dynamicCollection.add(b);
assertFalse(dynamicCollection.remove(a));
assertTrue(dynamicCollection.remove(b));
assertFalse(dynamicCollection.remove(b));
}
public void testCorrectExceptionThrownByIteratorWhenStructureChanges() {
Object a = new Object();
dynamicCollection.add(a);
dynamicCollection.add(a);
Iterator i1 = dynamicCollection.iterator();
iter.next();
iter.next();
i1.next();
i1.remove();
i1.next();
i1.remove();
assertFalse(i1.hasNext());
assertFalse(iter.hasNext());
try {
iter.remove();
fail("should have thrown exception");
}
catch (IndexOutOfBoundsException ioobe) {
// expected
}
}
// consistency tests
// 1. hasNext() reflects the latest collection updates (adding stuff)
public void testConsistentIteratorWhileAdding() throws Exception {
assertTrue(dynamicCollection.isEmpty());
assertFalse(iter.hasNext());
Object a = new Object();
dynamicCollection.add(a);
assertTrue(iter.hasNext());
assertSame(a, iter.next());
assertFalse(iter.hasNext());
}
// 1. hasNext() reflect the changes when removing things
public void testConsistentIteratorWhileRemoving() throws Exception {
assertTrue(dynamicCollection.isEmpty());
assertFalse(iter.hasNext());
Object a = new Object();
dynamicCollection.add(a);
assertTrue(iter.hasNext());
dynamicCollection.remove(a);
assertFalse(iter.hasNext());
}
// 2. hasNext() returns false -> next() throws Exception
public void testConsistentIteratorWithAddition() throws Exception {
assertTrue(dynamicCollection.isEmpty());
assertFalse(iter.hasNext());
Object a = new Object();
dynamicCollection.add(a);
try {
iter.next();
fail("the iterator is inconsistent - since hasNext() returned false, next() should fail");
}
catch (NoSuchElementException e) {
// expected
}
}
// 3. hasNext() = true -> next() will NOT throw an exception no matter the
// collection changes
public void testConsistentIterator() throws Exception {
assertTrue(dynamicCollection.isEmpty());
assertFalse(iter.hasNext());
Object a = new Object();
dynamicCollection.add(a);
assertTrue(iter.hasNext());
dynamicCollection.remove(a);
assertSame(a, iter.next()); // should successed
}
// 4. double check hasNext() true -> next() will return the last object for each
// iterator
public void testMultiIteratorHasNextConsistency() throws Exception {
assertTrue(dynamicCollection.isEmpty());
assertFalse(iter.hasNext());
Iterator iter1 = dynamicCollection.iterator();
Object a = new Object();
Object b = new Object();
Object c = new Object();
dynamicCollection.add(a);
dynamicCollection.add(b);
Iterator iter2 = dynamicCollection.iterator();
dynamicCollection.add(c);
Iterator iter3 = dynamicCollection.iterator();
// iter2 goes in the middle
assertSame(a, iter2.next());
// iter3 approaches the end
assertSame(a, iter3.next());
assertSame(b, iter3.next());
// check hasNext() and force next()
assertTrue(iter3.hasNext());
assertTrue(iter1.hasNext());
assertTrue(iter2.hasNext());
dynamicCollection.remove(c);
dynamicCollection.remove(b);
dynamicCollection.remove(a);
assertSame(a, iter1.next());
assertSame(b, iter2.next());
assertSame(c, iter3.next());
}
// similar test to the one above but the removal order is different
public void testMultiIteratorHasNextConsistencyGhostUpdate() throws Exception {
assertTrue(dynamicCollection.isEmpty());
assertFalse(iter.hasNext());
Iterator iter1 = dynamicCollection.iterator();
Object a = new Object();
Object b = new Object();
Object c = new Object();
dynamicCollection.add(a);
dynamicCollection.add(b);
Iterator iter2 = dynamicCollection.iterator();
dynamicCollection.add(c);
Iterator iter3 = dynamicCollection.iterator();
// iter2 goes in the middle
assertSame(a, iter2.next());
// iter3 approaches the end
assertSame(a, iter3.next());
assertSame(b, iter3.next());
// check hasNext() and force next()
assertTrue(iter3.hasNext());
assertTrue(iter1.hasNext());
assertTrue(iter2.hasNext());
dynamicCollection.remove(a);
dynamicCollection.remove(b);
dynamicCollection.remove(c);
assertSame(c, iter1.next());
assertSame(c, iter2.next());
assertSame(c, iter3.next());
}
public void testMultipleIteratorsPositionAfterCompleteRemoval() throws Exception {
Iterator iter1 = dynamicCollection.iterator();
Object a = new Object();
Object b = new Object();
Object c = new Object();
dynamicCollection.add(a);
dynamicCollection.add(b);
dynamicCollection.add(c);
Iterator iter2 = dynamicCollection.iterator();
// iter1 goes in the middle
assertSame(a, iter1.next());
// iter2 approaches the end
assertSame(a, iter2.next());
assertSame(b, iter2.next());
// check hasNext() and force next()
assertTrue(iter1.hasNext());
assertTrue(iter2.hasNext());
dynamicCollection.remove(c);
dynamicCollection.remove(b);
dynamicCollection.remove(a);
assertSame(b, iter1.next());
assertSame(c, iter2.next());
dynamicCollection.add(a);
// note: the iterator will return the previous elements if they've just been added to the collection
assertSame(a, iter1.next());
assertSame(a, iter2.next());
}
}