/* * 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(); } }