blob: 5bd5191484f3cf602ad2e9532b22bee4083dc457 [file] [log] [blame]
/*
* 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.
*/
package org.apache.commons.collections.iterators;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import org.apache.commons.collections.MapIterator;
/**
* Abstract class for testing the MapIterator interface.
* <p>
* This class provides a framework for testing an implementation of MapIterator.
* 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: 646780 $ $Date: 2008-04-10 13:48:07 +0100 (Thu, 10 Apr 2008) $
*
* @author Stephen Colebourne
*/
public abstract class AbstractTestMapIterator extends AbstractTestIterator {
/**
* JUnit constructor.
*
* @param testName the test class name
*/
public AbstractTestMapIterator(String testName) {
super(testName);
}
//-----------------------------------------------------------------------
/**
* Implement this method to return a map iterator over an empty map.
*
* @return an empty iterator
*/
public abstract MapIterator makeEmptyMapIterator();
/**
* Implement this method to return a map iterator over a map with elements.
*
* @return a full iterator
*/
public abstract MapIterator makeFullMapIterator();
/**
* Implement this method to return the map which contains the same data as the
* iterator.
*
* @return a full map which can be updated
*/
public abstract Map getMap();
/**
* Implement this method to return the confirmed map which contains the same
* data as the iterator.
*
* @return a full map which can be updated
*/
public abstract Map getConfirmedMap();
/**
* Implements the abstract superclass method to return the list iterator.
*
* @return an empty iterator
*/
public final Iterator makeEmptyIterator() {
return makeEmptyMapIterator();
}
/**
* Implements the abstract superclass method to return the list iterator.
*
* @return a full iterator
*/
public final Iterator makeFullIterator() {
return makeFullMapIterator();
}
/**
* Whether or not we are testing an iterator that supports setValue().
* Default is true.
*
* @return true if Iterator supports set
*/
public boolean supportsSetValue() {
return true;
}
/**
* Whether the get operation on the map structurally modifies the map,
* such as with LRUMap. Default is false.
*
* @return true if the get method structurally modifies the map
*/
public boolean isGetStructuralModify() {
return false;
}
/**
* The values to be used in the add and set tests.
* Default is two strings.
*/
public Object[] addSetValues() {
return new Object[] {"A", "B"};
}
//-----------------------------------------------------------------------
/**
* Test that the empty list iterator contract is correct.
*/
public void testEmptyMapIterator() {
if (supportsEmptyIterator() == false) {
return;
}
MapIterator it = makeEmptyMapIterator();
Map map = getMap();
assertEquals(false, it.hasNext());
// next() should throw a NoSuchElementException
try {
it.next();
fail();
} catch (NoSuchElementException ex) {}
// getKey() should throw an IllegalStateException
try {
it.getKey();
fail();
} catch (IllegalStateException ex) {}
// getValue() should throw an IllegalStateException
try {
it.getValue();
fail();
} catch (IllegalStateException ex) {}
if (supportsSetValue() == false) {
// setValue() should throw an UnsupportedOperationException/IllegalStateException
try {
it.setValue(addSetValues()[0]);
fail();
} catch (UnsupportedOperationException ex) {
} catch (IllegalStateException ex) {}
} else {
// setValue() should throw an IllegalStateException
try {
it.setValue(addSetValues()[0]);
fail();
} catch (IllegalStateException ex) {}
}
}
//-----------------------------------------------------------------------
/**
* Test that the full list iterator contract is correct.
*/
public void testFullMapIterator() {
if (supportsFullIterator() == false) {
return;
}
MapIterator it = makeFullMapIterator();
Map map = getMap();
assertEquals(true, it.hasNext());
assertEquals(true, it.hasNext());
Set set = new HashSet();
while (it.hasNext()) {
// getKey
Object key = it.next();
assertSame("it.next() should equals getKey()", key, it.getKey());
assertTrue("Key must be in map", map.containsKey(key));
assertTrue("Key must be unique", set.add(key));
// getValue
Object value = it.getValue();
if (isGetStructuralModify() == false) {
assertSame("Value must be mapped to key", map.get(key), value);
}
assertTrue("Value must be in map", map.containsValue(value));
verify();
}
}
//-----------------------------------------------------------------------
public void testMapIteratorSet() {
if (supportsFullIterator() == false) {
return;
}
Object newValue = addSetValues()[0];
Object newValue2 = (addSetValues().length == 1 ? addSetValues()[0] : addSetValues()[1]);
MapIterator it = makeFullMapIterator();
Map map = getMap();
Map confirmed = getConfirmedMap();
assertEquals(true, it.hasNext());
Object key = it.next();
Object value = it.getValue();
if (supportsSetValue() == false) {
try {
it.setValue(newValue);
fail();
} catch (UnsupportedOperationException ex) {}
return;
}
Object old = it.setValue(newValue);
confirmed.put(key, newValue);
assertSame("Key must not change after setValue", key, it.getKey());
assertSame("Value must be changed after setValue", newValue, it.getValue());
assertSame("setValue must return old value", value, old);
assertEquals("Map must contain key", true, map.containsKey(key));
// test against confirmed, as map may contain value twice
assertEquals("Map must not contain old value",
confirmed.containsValue(old), map.containsValue(old));
assertEquals("Map must contain new value", true, map.containsValue(newValue));
verify();
it.setValue(newValue); // same value - should be OK
confirmed.put(key, newValue);
assertSame("Key must not change after setValue", key, it.getKey());
assertSame("Value must be changed after setValue", newValue, it.getValue());
verify();
it.setValue(newValue2); // new value
confirmed.put(key, newValue2);
assertSame("Key must not change after setValue", key, it.getKey());
assertSame("Value must be changed after setValue", newValue2, it.getValue());
verify();
}
//-----------------------------------------------------------------------
public void testRemove() { // override
MapIterator it = makeFullMapIterator();
Map map = getMap();
Map confirmed = getConfirmedMap();
assertEquals(true, it.hasNext());
Object key = it.next();
if (supportsRemove() == false) {
try {
it.remove();
fail();
} catch (UnsupportedOperationException ex) {
}
return;
}
it.remove();
confirmed.remove(key);
assertEquals(false, map.containsKey(key));
verify();
try {
it.remove(); // second remove fails
} catch (IllegalStateException ex) {
}
verify();
}
//-----------------------------------------------------------------------
public void testMapIteratorSetRemoveSet() {
if (supportsSetValue() == false || supportsRemove() == false) {
return;
}
Object newValue = addSetValues()[0];
MapIterator it = makeFullMapIterator();
Map map = getMap();
Map confirmed = getConfirmedMap();
assertEquals(true, it.hasNext());
Object key = it.next();
it.setValue(newValue);
it.remove();
confirmed.remove(key);
verify();
try {
it.setValue(newValue);
fail();
} catch (IllegalStateException ex) {}
verify();
}
//-----------------------------------------------------------------------
public void testMapIteratorRemoveGetKey() {
if (supportsRemove() == false) {
return;
}
MapIterator it = makeFullMapIterator();
Map map = getMap();
Map confirmed = getConfirmedMap();
assertEquals(true, it.hasNext());
Object key = it.next();
it.remove();
confirmed.remove(key);
verify();
try {
it.getKey();
fail();
} catch (IllegalStateException ex) {}
verify();
}
//-----------------------------------------------------------------------
public void testMapIteratorRemoveGetValue() {
if (supportsRemove() == false) {
return;
}
MapIterator it = makeFullMapIterator();
Map map = getMap();
Map confirmed = getConfirmedMap();
assertEquals(true, it.hasNext());
Object key = it.next();
it.remove();
confirmed.remove(key);
verify();
try {
it.getValue();
fail();
} catch (IllegalStateException ex) {}
verify();
}
}