--- jsr166/src/test/tck/TreeMapTest.java 2004/12/28 16:15:59 1.1 +++ jsr166/src/test/tck/TreeMapTest.java 2021/01/26 13:33:06 1.36 @@ -1,222 +1,284 @@ /* * Written by Doug Lea with assistance from members of JCP JSR-166 * Expert Group and released to the public domain, as explained at - * http://creativecommons.org/licenses/publicdomain + * http://creativecommons.org/publicdomain/zero/1.0/ */ -import junit.framework.*; -import java.util.*; -import java.util.concurrent.*; -import java.io.*; +import java.util.Arrays; +import java.util.BitSet; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.NavigableMap; +import java.util.NavigableSet; +import java.util.NoSuchElementException; +import java.util.Random; +import java.util.Set; +import java.util.TreeMap; + +import junit.framework.Test; public class TreeMapTest extends JSR166TestCase { public static void main(String[] args) { - junit.textui.TestRunner.run (suite()); + main(suite(), args); } public static Test suite() { - return new TestSuite(TreeMapTest.class); + class Implementation implements MapImplementation { + public Class klazz() { return TreeMap.class; } + public Map emptyMap() { return new TreeMap(); } + public boolean isConcurrent() { return false; } + public boolean permitsNullKeys() { return false; } + public boolean permitsNullValues() { return true; } + public boolean supportsSetValue() { return true; } + } + return newTestSuite( + TreeMapTest.class, + MapTest.testSuite(new Implementation())); } /** - * Create a map from Integers 1-5 to Strings "A"-"E". + * Returns a new map from Items 1-5 to Strings "A"-"E". */ - private static TreeMap map5() { - TreeMap map = new TreeMap(); + private static TreeMap map5() { + TreeMap map = new TreeMap(); assertTrue(map.isEmpty()); - map.put(one, "A"); - map.put(five, "E"); - map.put(three, "C"); - map.put(two, "B"); - map.put(four, "D"); + map.put(one, "A"); + map.put(five, "E"); + map.put(three, "C"); + map.put(two, "B"); + map.put(four, "D"); assertFalse(map.isEmpty()); - assertEquals(5, map.size()); - return map; + mustEqual(5, map.size()); + return map; } /** - * clear removes all pairs + * clear removes all pairs */ public void testClear() { - TreeMap map = map5(); - map.clear(); - assertEquals(map.size(), 0); + TreeMap map = map5(); + map.clear(); + mustEqual(0, map.size()); } /** - * + * copy constructor creates map equal to source map */ public void testConstructFromSorted() { - TreeMap map = map5(); - TreeMap map2 = new TreeMap(map); - assertEquals(map, map2); + TreeMap map = map5(); + TreeMap map2 = new TreeMap(map); + mustEqual(map, map2); } /** - * Maps with same contents are equal + * Maps with same contents are equal */ public void testEquals() { - TreeMap map1 = map5(); - TreeMap map2 = map5(); - assertEquals(map1, map2); - assertEquals(map2, map1); - map1.clear(); + TreeMap map1 = map5(); + TreeMap map2 = map5(); + mustEqual(map1, map2); + mustEqual(map2, map1); + map1.clear(); assertFalse(map1.equals(map2)); assertFalse(map2.equals(map1)); } /** - * containsKey returns true for contained key + * containsKey returns true for contained key */ public void testContainsKey() { - TreeMap map = map5(); - assertTrue(map.containsKey(one)); + TreeMap map = map5(); + assertTrue(map.containsKey(one)); assertFalse(map.containsKey(zero)); } /** - * containsValue returns true for held values + * containsValue returns true for held values */ public void testContainsValue() { - TreeMap map = map5(); - assertTrue(map.containsValue("A")); + TreeMap map = map5(); + assertTrue(map.containsValue("A")); assertFalse(map.containsValue("Z")); } /** - * get returns the correct element at the given key, - * or null if not present + * get returns the correct element at the given key, + * or null if not present */ public void testGet() { - TreeMap map = map5(); - assertEquals("A", (String)map.get(one)); - TreeMap empty = new TreeMap(); + TreeMap map = map5(); + mustEqual("A", map.get(one)); + TreeMap empty = new TreeMap(); assertNull(empty.get(one)); } /** - * isEmpty is true of empty map and false for non-empty + * isEmpty is true of empty map and false for non-empty */ public void testIsEmpty() { - TreeMap empty = new TreeMap(); - TreeMap map = map5(); - assertTrue(empty.isEmpty()); + TreeMap empty = new TreeMap(); + TreeMap map = map5(); + assertTrue(empty.isEmpty()); assertFalse(map.isEmpty()); } /** - * firstKey returns first key + * firstKey returns first key */ public void testFirstKey() { - TreeMap map = map5(); - assertEquals(one, map.firstKey()); + TreeMap map = map5(); + mustEqual(one, map.firstKey()); } /** - * lastKey returns last key + * lastKey returns last key */ public void testLastKey() { - TreeMap map = map5(); - assertEquals(five, map.lastKey()); + TreeMap map = map5(); + mustEqual(five, map.lastKey()); } - /** - * keySet.toArray returns contains all keys + * keySet.toArray returns contains all keys */ public void testKeySetToArray() { - TreeMap map = map5(); - Set s = map.keySet(); + TreeMap map = map5(); + Set s = map.keySet(); Object[] ar = s.toArray(); assertTrue(s.containsAll(Arrays.asList(ar))); - assertEquals(5, ar.length); - ar[0] = m10; + mustEqual(5, ar.length); + ar[0] = minusTen; assertFalse(s.containsAll(Arrays.asList(ar))); } /** - * descendingkeySet.toArray returns contains all keys + * descendingkeySet.toArray returns contains all keys */ public void testDescendingKeySetToArray() { - TreeMap map = map5(); - Set s = map.descendingKeySet(); + TreeMap map = map5(); + Set s = map.descendingKeySet(); Object[] ar = s.toArray(); - assertEquals(5, ar.length); + mustEqual(5, ar.length); assertTrue(s.containsAll(Arrays.asList(ar))); - ar[0] = m10; + ar[0] = minusTen; assertFalse(s.containsAll(Arrays.asList(ar))); } /** - * keySet returns a Set containing all the keys + * keySet returns a Set containing all the keys */ public void testKeySet() { - TreeMap map = map5(); - Set s = map.keySet(); - assertEquals(5, s.size()); - assertTrue(s.contains(one)); - assertTrue(s.contains(two)); - assertTrue(s.contains(three)); - assertTrue(s.contains(four)); - assertTrue(s.contains(five)); + TreeMap map = map5(); + Set s = map.keySet(); + mustEqual(5, s.size()); + mustContain(s, one); + mustContain(s, two); + mustContain(s, three); + mustContain(s, four); + mustContain(s, five); } /** - * keySet is ordered + * keySet is ordered */ public void testKeySetOrder() { - TreeMap map = map5(); - Set s = map.keySet(); - Iterator i = s.iterator(); - Integer last = (Integer)i.next(); - assertEquals(last, one); + TreeMap map = map5(); + Set s = map.keySet(); + Iterator i = s.iterator(); + Item last = i.next(); + mustEqual(last, one); + int count = 1; while (i.hasNext()) { - Integer k = (Integer)i.next(); + Item k = i.next(); assertTrue(last.compareTo(k) < 0); last = k; + ++count; } + mustEqual(5, count); } /** - * descendingKeySet is ordered + * descending iterator of key set is inverse ordered + */ + public void testKeySetDescendingIteratorOrder() { + TreeMap map = map5(); + NavigableSet s = map.navigableKeySet(); + Iterator i = s.descendingIterator(); + Item last = (Item)i.next(); + mustEqual(last, five); + int count = 1; + while (i.hasNext()) { + Item k = (Item)i.next(); + assertTrue(last.compareTo(k) > 0); + last = k; + ++count; + } + mustEqual(5, count); + } + + /** + * descendingKeySet is ordered */ public void testDescendingKeySetOrder() { - TreeMap map = map5(); - Set s = map.descendingKeySet(); - Iterator i = s.iterator(); - Integer last = (Integer)i.next(); - assertEquals(last, five); + TreeMap map = map5(); + Set s = map.descendingKeySet(); + Iterator i = s.iterator(); + Item last = (Item)i.next(); + mustEqual(last, five); + int count = 1; while (i.hasNext()) { - Integer k = (Integer)i.next(); + Item k = (Item)i.next(); assertTrue(last.compareTo(k) > 0); last = k; + ++count; } + mustEqual(5, count); + } + + /** + * descending iterator of descendingKeySet is ordered + */ + public void testDescendingKeySetDescendingIteratorOrder() { + TreeMap map = map5(); + NavigableSet s = map.descendingKeySet(); + Iterator i = s.descendingIterator(); + Item last = (Item)i.next(); + mustEqual(last, one); + int count = 1; + while (i.hasNext()) { + Item k = (Item)i.next(); + assertTrue(last.compareTo(k) < 0); + last = k; + ++count; + } + mustEqual(5, count); } /** * values collection contains all values */ public void testValues() { - TreeMap map = map5(); - Collection s = map.values(); - assertEquals(5, s.size()); - assertTrue(s.contains("A")); - assertTrue(s.contains("B")); - assertTrue(s.contains("C")); - assertTrue(s.contains("D")); - assertTrue(s.contains("E")); + TreeMap map = map5(); + Collection s = map.values(); + mustEqual(5, s.size()); + assertTrue(s.contains("A")); + assertTrue(s.contains("B")); + assertTrue(s.contains("C")); + assertTrue(s.contains("D")); + assertTrue(s.contains("E")); } /** * entrySet contains all pairs */ public void testEntrySet() { - TreeMap map = map5(); - Set s = map.entrySet(); - assertEquals(5, s.size()); - Iterator it = s.iterator(); + TreeMap map = map5(); + Set> s = map.entrySet(); + mustEqual(5, s.size()); + Iterator> it = s.iterator(); while (it.hasNext()) { - Map.Entry e = (Map.Entry) it.next(); - assertTrue( + Map.Entry e = it.next(); + assertTrue( (e.getKey().equals(one) && e.getValue().equals("A")) || (e.getKey().equals(two) && e.getValue().equals("B")) || (e.getKey().equals(three) && e.getValue().equals("C")) || @@ -229,13 +291,13 @@ public class TreeMapTest extends JSR166T * descendingEntrySet contains all pairs */ public void testDescendingEntrySet() { - TreeMap map = map5(); - Set s = map.descendingEntrySet(); - assertEquals(5, s.size()); - Iterator it = s.iterator(); + TreeMap map = map5(); + Set> s = map.descendingMap().entrySet(); + mustEqual(5, s.size()); + Iterator> it = s.iterator(); while (it.hasNext()) { - Map.Entry e = (Map.Entry) it.next(); - assertTrue( + Map.Entry e = it.next(); + assertTrue( (e.getKey().equals(one) && e.getValue().equals("A")) || (e.getKey().equals(two) && e.getValue().equals("B")) || (e.getKey().equals(three) && e.getValue().equals("C")) || @@ -245,13 +307,13 @@ public class TreeMapTest extends JSR166T } /** - * entrySet.toArray contains all entries + * entrySet.toArray contains all entries */ public void testEntrySetToArray() { - TreeMap map = map5(); - Set s = map.entrySet(); + TreeMap map = map5(); + Set> s = map.entrySet(); Object[] ar = s.toArray(); - assertEquals(5, ar.length); + mustEqual(5, ar.length); for (int i = 0; i < 5; ++i) { assertTrue(map.containsKey(((Map.Entry)(ar[i])).getKey())); assertTrue(map.containsValue(((Map.Entry)(ar[i])).getValue())); @@ -259,13 +321,13 @@ public class TreeMapTest extends JSR166T } /** - * descendingEntrySet.toArray contains all entries + * descendingEntrySet.toArray contains all entries */ public void testDescendingEntrySetToArray() { - TreeMap map = map5(); - Set s = map.descendingEntrySet(); + TreeMap map = map5(); + Set> s = map.descendingMap().entrySet(); Object[] ar = s.toArray(); - assertEquals(5, ar.length); + mustEqual(5, ar.length); for (int i = 0; i < 5; ++i) { assertTrue(map.containsKey(((Map.Entry)(ar[i])).getKey())); assertTrue(map.containsValue(((Map.Entry)(ar[i])).getValue())); @@ -273,207 +335,197 @@ public class TreeMapTest extends JSR166T } /** - * putAll adds all key-value pairs from the given map + * putAll adds all key-value pairs from the given map */ public void testPutAll() { - TreeMap empty = new TreeMap(); - TreeMap map = map5(); - empty.putAll(map); - assertEquals(5, empty.size()); - assertTrue(empty.containsKey(one)); - assertTrue(empty.containsKey(two)); - assertTrue(empty.containsKey(three)); - assertTrue(empty.containsKey(four)); - assertTrue(empty.containsKey(five)); + TreeMap empty = new TreeMap(); + TreeMap map = map5(); + empty.putAll(map); + mustEqual(5, empty.size()); + assertTrue(empty.containsKey(one)); + assertTrue(empty.containsKey(two)); + assertTrue(empty.containsKey(three)); + assertTrue(empty.containsKey(four)); + assertTrue(empty.containsKey(five)); } /** - * remove removes the correct key-value pair from the map + * remove removes the correct key-value pair from the map */ public void testRemove() { - TreeMap map = map5(); - map.remove(five); - assertEquals(4, map.size()); - assertFalse(map.containsKey(five)); + TreeMap map = map5(); + map.remove(five); + mustEqual(4, map.size()); + assertFalse(map.containsKey(five)); } /** * lowerEntry returns preceding entry. */ public void testLowerEntry() { - TreeMap map = map5(); - Map.Entry e1 = map.lowerEntry(three); - assertEquals(two, e1.getKey()); + TreeMap map = map5(); + Map.Entry e1 = map.lowerEntry(three); + mustEqual(two, e1.getKey()); - Map.Entry e2 = map.lowerEntry(six); - assertEquals(five, e2.getKey()); + Map.Entry e2 = map.lowerEntry(six); + mustEqual(five, e2.getKey()); - Map.Entry e3 = map.lowerEntry(one); + Map.Entry e3 = map.lowerEntry(one); assertNull(e3); - Map.Entry e4 = map.lowerEntry(zero); + Map.Entry e4 = map.lowerEntry(zero); assertNull(e4); - } /** * higherEntry returns next entry. */ public void testHigherEntry() { - TreeMap map = map5(); - Map.Entry e1 = map.higherEntry(three); - assertEquals(four, e1.getKey()); + TreeMap map = map5(); + Map.Entry e1 = map.higherEntry(three); + mustEqual(four, e1.getKey()); - Map.Entry e2 = map.higherEntry(zero); - assertEquals(one, e2.getKey()); + Map.Entry e2 = map.higherEntry(zero); + mustEqual(one, e2.getKey()); - Map.Entry e3 = map.higherEntry(five); + Map.Entry e3 = map.higherEntry(five); assertNull(e3); - Map.Entry e4 = map.higherEntry(six); + Map.Entry e4 = map.higherEntry(six); assertNull(e4); - } /** * floorEntry returns preceding entry. */ public void testFloorEntry() { - TreeMap map = map5(); - Map.Entry e1 = map.floorEntry(three); - assertEquals(three, e1.getKey()); + TreeMap map = map5(); + Map.Entry e1 = map.floorEntry(three); + mustEqual(three, e1.getKey()); - Map.Entry e2 = map.floorEntry(six); - assertEquals(five, e2.getKey()); + Map.Entry e2 = map.floorEntry(six); + mustEqual(five, e2.getKey()); - Map.Entry e3 = map.floorEntry(one); - assertEquals(one, e3.getKey()); + Map.Entry e3 = map.floorEntry(one); + mustEqual(one, e3.getKey()); - Map.Entry e4 = map.floorEntry(zero); + Map.Entry e4 = map.floorEntry(zero); assertNull(e4); - } /** * ceilingEntry returns next entry. */ public void testCeilingEntry() { - TreeMap map = map5(); - Map.Entry e1 = map.ceilingEntry(three); - assertEquals(three, e1.getKey()); + TreeMap map = map5(); + Map.Entry e1 = map.ceilingEntry(three); + mustEqual(three, e1.getKey()); - Map.Entry e2 = map.ceilingEntry(zero); - assertEquals(one, e2.getKey()); + Map.Entry e2 = map.ceilingEntry(zero); + mustEqual(one, e2.getKey()); - Map.Entry e3 = map.ceilingEntry(five); - assertEquals(five, e3.getKey()); + Map.Entry e3 = map.ceilingEntry(five); + mustEqual(five, e3.getKey()); - Map.Entry e4 = map.ceilingEntry(six); + Map.Entry e4 = map.ceilingEntry(six); assertNull(e4); - } - /** * lowerKey returns preceding element */ public void testLowerKey() { - TreeMap q = map5(); + TreeMap q = map5(); Object e1 = q.lowerKey(three); - assertEquals(two, e1); + mustEqual(two, e1); Object e2 = q.lowerKey(six); - assertEquals(five, e2); + mustEqual(five, e2); Object e3 = q.lowerKey(one); assertNull(e3); Object e4 = q.lowerKey(zero); assertNull(e4); - } /** * higherKey returns next element */ public void testHigherKey() { - TreeMap q = map5(); + TreeMap q = map5(); Object e1 = q.higherKey(three); - assertEquals(four, e1); + mustEqual(four, e1); Object e2 = q.higherKey(zero); - assertEquals(one, e2); + mustEqual(one, e2); Object e3 = q.higherKey(five); assertNull(e3); Object e4 = q.higherKey(six); assertNull(e4); - } /** * floorKey returns preceding element */ public void testFloorKey() { - TreeMap q = map5(); + TreeMap q = map5(); Object e1 = q.floorKey(three); - assertEquals(three, e1); + mustEqual(three, e1); Object e2 = q.floorKey(six); - assertEquals(five, e2); + mustEqual(five, e2); Object e3 = q.floorKey(one); - assertEquals(one, e3); + mustEqual(one, e3); Object e4 = q.floorKey(zero); assertNull(e4); - } /** * ceilingKey returns next element */ public void testCeilingKey() { - TreeMap q = map5(); + TreeMap q = map5(); Object e1 = q.ceilingKey(three); - assertEquals(three, e1); + mustEqual(three, e1); Object e2 = q.ceilingKey(zero); - assertEquals(one, e2); + mustEqual(one, e2); Object e3 = q.ceilingKey(five); - assertEquals(five, e3); + mustEqual(five, e3); Object e4 = q.ceilingKey(six); assertNull(e4); - } /** * pollFirstEntry returns entries in order */ public void testPollFirstEntry() { - TreeMap map = map5(); - Map.Entry e = map.pollFirstEntry(); - assertEquals(one, e.getKey()); - assertEquals("A", e.getValue()); + TreeMap map = map5(); + Map.Entry e = map.pollFirstEntry(); + mustEqual(one, e.getKey()); + mustEqual("A", e.getValue()); e = map.pollFirstEntry(); - assertEquals(two, e.getKey()); + mustEqual(two, e.getKey()); map.put(one, "A"); e = map.pollFirstEntry(); - assertEquals(one, e.getKey()); - assertEquals("A", e.getValue()); + mustEqual(one, e.getKey()); + mustEqual("A", e.getValue()); e = map.pollFirstEntry(); - assertEquals(three, e.getKey()); + mustEqual(three, e.getKey()); map.remove(four); e = map.pollFirstEntry(); - assertEquals(five, e.getKey()); + mustEqual(five, e.getKey()); try { e.setValue("A"); shouldThrow(); - } catch (Exception ok) { - } + } catch (UnsupportedOperationException success) {} e = map.pollFirstEntry(); assertNull(e); } @@ -482,50 +534,49 @@ public class TreeMapTest extends JSR166T * pollLastEntry returns entries in order */ public void testPollLastEntry() { - TreeMap map = map5(); - Map.Entry e = map.pollLastEntry(); - assertEquals(five, e.getKey()); - assertEquals("E", e.getValue()); + TreeMap map = map5(); + Map.Entry e = map.pollLastEntry(); + mustEqual(five, e.getKey()); + mustEqual("E", e.getValue()); e = map.pollLastEntry(); - assertEquals(four, e.getKey()); + mustEqual(four, e.getKey()); map.put(five, "E"); e = map.pollLastEntry(); - assertEquals(five, e.getKey()); - assertEquals("E", e.getValue()); + mustEqual(five, e.getKey()); + mustEqual("E", e.getValue()); e = map.pollLastEntry(); - assertEquals(three, e.getKey()); + mustEqual(three, e.getKey()); map.remove(two); e = map.pollLastEntry(); - assertEquals(one, e.getKey()); + mustEqual(one, e.getKey()); try { e.setValue("E"); shouldThrow(); - } catch (Exception ok) { - } + } catch (UnsupportedOperationException success) {} e = map.pollLastEntry(); assertNull(e); } /** - * size returns the correct values + * size returns the correct values */ public void testSize() { - TreeMap map = map5(); - TreeMap empty = new TreeMap(); - assertEquals(0, empty.size()); - assertEquals(5, map.size()); + TreeMap map = map5(); + TreeMap empty = new TreeMap(); + mustEqual(0, empty.size()); + mustEqual(5, map.size()); } /** * toString contains toString of elements */ public void testToString() { - TreeMap map = map5(); + TreeMap map = map5(); String s = map.toString(); for (int i = 1; i <= 5; ++i) { - assertTrue(s.indexOf(String.valueOf(i)) >= 0); + assertTrue(s.contains(String.valueOf(i))); } - } + } // Exception tests @@ -533,215 +584,511 @@ public class TreeMapTest extends JSR166T * get(null) of nonempty map throws NPE */ public void testGet_NullPointerException() { + TreeMap c = map5(); try { - TreeMap c = map5(); c.get(null); shouldThrow(); - } catch(NullPointerException e){} + } catch (NullPointerException success) {} } /** * containsKey(null) of nonempty map throws NPE */ public void testContainsKey_NullPointerException() { + TreeMap c = map5(); try { - TreeMap c = map5(); c.containsKey(null); shouldThrow(); - } catch(NullPointerException e){} + } catch (NullPointerException success) {} } /** * remove(null) throws NPE for nonempty map */ public void testRemove1_NullPointerException() { + TreeMap c = new TreeMap(); + c.put(one, "asdads"); try { - TreeMap c = new TreeMap(); - c.put("sadsdf", "asdads"); c.remove(null); shouldThrow(); - } catch(NullPointerException e){} + } catch (NullPointerException success) {} } /** - * A deserialized map equals original + * A deserialized/reserialized map equals original */ - public void testSerialization() { - TreeMap q = map5(); + public void testSerialization() throws Exception { + NavigableMap x = map5(); + NavigableMap y = serialClone(x); - try { - ByteArrayOutputStream bout = new ByteArrayOutputStream(10000); - ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout)); - out.writeObject(q); - out.close(); - - ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); - ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin)); - TreeMap r = (TreeMap)in.readObject(); - assertEquals(q.size(), r.size()); - assertTrue(q.equals(r)); - assertTrue(r.equals(q)); - } catch(Exception e){ - e.printStackTrace(); - unexpectedException(); - } + assertNotSame(x, y); + mustEqual(x.size(), y.size()); + mustEqual(x.toString(), y.toString()); + mustEqual(x, y); + mustEqual(y, x); } /** * subMap returns map with keys in requested range */ public void testSubMapContents() { - TreeMap map = map5(); - NavigableMap sm = map.subMap(two, four); - assertEquals(two, sm.firstKey()); - assertEquals(three, sm.lastKey()); - assertEquals(2, sm.size()); + TreeMap map = map5(); + NavigableMap sm = map.subMap(two, true, four, false); + mustEqual(two, sm.firstKey()); + mustEqual(three, sm.lastKey()); + mustEqual(2, sm.size()); assertFalse(sm.containsKey(one)); assertTrue(sm.containsKey(two)); assertTrue(sm.containsKey(three)); assertFalse(sm.containsKey(four)); assertFalse(sm.containsKey(five)); - Iterator i = sm.keySet().iterator(); - Object k; - k = (Integer)(i.next()); - assertEquals(two, k); - k = (Integer)(i.next()); - assertEquals(three, k); + Iterator i = sm.keySet().iterator(); + Item k; + k = (Item)(i.next()); + mustEqual(two, k); + k = (Item)(i.next()); + mustEqual(three, k); assertFalse(i.hasNext()); - Iterator r = sm.descendingKeySet().iterator(); - k = (Integer)(r.next()); - assertEquals(three, k); - k = (Integer)(r.next()); - assertEquals(two, k); + Iterator r = sm.descendingKeySet().iterator(); + k = (Item)(r.next()); + mustEqual(three, k); + k = (Item)(r.next()); + mustEqual(two, k); assertFalse(r.hasNext()); - - Iterator j = sm.keySet().iterator(); + + Iterator j = sm.keySet().iterator(); j.next(); j.remove(); assertFalse(map.containsKey(two)); - assertEquals(4, map.size()); - assertEquals(1, sm.size()); - assertEquals(three, sm.firstKey()); - assertEquals(three, sm.lastKey()); - assertTrue(sm.remove(three) != null); + mustEqual(4, map.size()); + mustEqual(1, sm.size()); + mustEqual(three, sm.firstKey()); + mustEqual(three, sm.lastKey()); + mustEqual("C", sm.remove(three)); assertTrue(sm.isEmpty()); - assertEquals(3, map.size()); + mustEqual(3, map.size()); } public void testSubMapContents2() { - TreeMap map = map5(); - NavigableMap sm = map.subMap(two, three); - assertEquals(1, sm.size()); - assertEquals(two, sm.firstKey()); - assertEquals(two, sm.lastKey()); + TreeMap map = map5(); + NavigableMap sm = map.subMap(two, true, three, false); + mustEqual(1, sm.size()); + mustEqual(two, sm.firstKey()); + mustEqual(two, sm.lastKey()); assertFalse(sm.containsKey(one)); assertTrue(sm.containsKey(two)); assertFalse(sm.containsKey(three)); assertFalse(sm.containsKey(four)); assertFalse(sm.containsKey(five)); - Iterator i = sm.keySet().iterator(); - Object k; - k = (Integer)(i.next()); - assertEquals(two, k); + Iterator i = sm.keySet().iterator(); + Item k; + k = (Item)(i.next()); + mustEqual(two, k); assertFalse(i.hasNext()); - Iterator r = sm.descendingKeySet().iterator(); - k = (Integer)(r.next()); - assertEquals(two, k); + Iterator r = sm.descendingKeySet().iterator(); + k = (Item)(r.next()); + mustEqual(two, k); assertFalse(r.hasNext()); - - Iterator j = sm.keySet().iterator(); + + Iterator j = sm.keySet().iterator(); j.next(); j.remove(); assertFalse(map.containsKey(two)); - assertEquals(4, map.size()); - assertEquals(0, sm.size()); + mustEqual(4, map.size()); + mustEqual(0, sm.size()); assertTrue(sm.isEmpty()); - assertTrue(sm.remove(three) == null); - assertEquals(4, map.size()); + assertSame(sm.remove(three), null); + mustEqual(4, map.size()); } /** * headMap returns map with keys in requested range */ public void testHeadMapContents() { - TreeMap map = map5(); - NavigableMap sm = map.headMap(four); + TreeMap map = map5(); + NavigableMap sm = map.headMap(four, false); assertTrue(sm.containsKey(one)); assertTrue(sm.containsKey(two)); assertTrue(sm.containsKey(three)); assertFalse(sm.containsKey(four)); assertFalse(sm.containsKey(five)); - Iterator i = sm.keySet().iterator(); - Object k; - k = (Integer)(i.next()); - assertEquals(one, k); - k = (Integer)(i.next()); - assertEquals(two, k); - k = (Integer)(i.next()); - assertEquals(three, k); + Iterator i = sm.keySet().iterator(); + Item k; + k = (Item)(i.next()); + mustEqual(one, k); + k = (Item)(i.next()); + mustEqual(two, k); + k = (Item)(i.next()); + mustEqual(three, k); assertFalse(i.hasNext()); sm.clear(); assertTrue(sm.isEmpty()); - assertEquals(2, map.size()); - assertEquals(four, map.firstKey()); + mustEqual(2, map.size()); + mustEqual(four, map.firstKey()); } /** * headMap returns map with keys in requested range */ public void testTailMapContents() { - TreeMap map = map5(); - NavigableMap sm = map.tailMap(two); + TreeMap map = map5(); + NavigableMap sm = map.tailMap(two, true); assertFalse(sm.containsKey(one)); assertTrue(sm.containsKey(two)); assertTrue(sm.containsKey(three)); assertTrue(sm.containsKey(four)); assertTrue(sm.containsKey(five)); - Iterator i = sm.keySet().iterator(); - Object k; - k = (Integer)(i.next()); - assertEquals(two, k); - k = (Integer)(i.next()); - assertEquals(three, k); - k = (Integer)(i.next()); - assertEquals(four, k); - k = (Integer)(i.next()); - assertEquals(five, k); + Iterator i = sm.keySet().iterator(); + Item k = (i.next()); + mustEqual(two, k); + k = (i.next()); + mustEqual(three, k); + k = (i.next()); + mustEqual(four, k); + k = (i.next()); + mustEqual(five, k); assertFalse(i.hasNext()); - Iterator r = sm.descendingKeySet().iterator(); - k = (Integer)(r.next()); - assertEquals(five, k); - k = (Integer)(r.next()); - assertEquals(four, k); - k = (Integer)(r.next()); - assertEquals(three, k); - k = (Integer)(r.next()); - assertEquals(two, k); + Iterator r = sm.descendingKeySet().iterator(); + k = (r.next()); + mustEqual(five, k); + k = (r.next()); + mustEqual(four, k); + k = (r.next()); + mustEqual(three, k); + k = (r.next()); + mustEqual(two, k); assertFalse(r.hasNext()); - Iterator ei = sm.entrySet().iterator(); - Map.Entry e; - e = (Map.Entry)(ei.next()); - assertEquals(two, e.getKey()); - assertEquals("B", e.getValue()); - e = (Map.Entry)(ei.next()); - assertEquals(three, e.getKey()); - assertEquals("C", e.getValue()); - e = (Map.Entry)(ei.next()); - assertEquals(four, e.getKey()); - assertEquals("D", e.getValue()); - e = (Map.Entry)(ei.next()); - assertEquals(five, e.getKey()); - assertEquals("E", e.getValue()); + Iterator> ei = sm.entrySet().iterator(); + Map.Entry e; + e = (ei.next()); + mustEqual(two, e.getKey()); + mustEqual("B", e.getValue()); + e = (ei.next()); + mustEqual(three, e.getKey()); + mustEqual("C", e.getValue()); + e = (ei.next()); + mustEqual(four, e.getKey()); + mustEqual("D", e.getValue()); + e = (ei.next()); + mustEqual(five, e.getKey()); + mustEqual("E", e.getValue()); assertFalse(i.hasNext()); - NavigableMap ssm = sm.tailMap(four); - assertEquals(four, ssm.firstKey()); - assertEquals(five, ssm.lastKey()); - assertTrue(ssm.remove(four) != null); - assertEquals(1, ssm.size()); - assertEquals(3, sm.size()); - assertEquals(4, map.size()); + NavigableMap ssm = sm.tailMap(four, true); + mustEqual(four, ssm.firstKey()); + mustEqual(five, ssm.lastKey()); + mustEqual("D", ssm.remove(four)); + mustEqual(1, ssm.size()); + mustEqual(3, sm.size()); + mustEqual(4, map.size()); + } + + Random rnd = new Random(666); + BitSet bs; + + /** + * Submaps of submaps subdivide correctly + */ + public void testRecursiveSubMaps() throws Exception { + int mapSize = expensiveTests ? 1000 : 100; + Class cl = TreeMap.class; + NavigableMap map = newMap(cl); + bs = new BitSet(mapSize); + + populate(map, mapSize); + check(map, 0, mapSize - 1, true); + check(map.descendingMap(), 0, mapSize - 1, false); + + mutateMap(map, 0, mapSize - 1); + check(map, 0, mapSize - 1, true); + check(map.descendingMap(), 0, mapSize - 1, false); + + bashSubMap(map.subMap(zero, true, itemFor(mapSize), false), + 0, mapSize - 1, true); } - + + static NavigableMap newMap(Class cl) throws Exception { + @SuppressWarnings("unchecked") + NavigableMap result + = (NavigableMap) cl.getConstructor().newInstance(); + mustEqual(0, result.size()); + assertFalse(result.keySet().iterator().hasNext()); + return result; + } + + void populate(NavigableMap map, int limit) { + for (int i = 0, n = 2 * limit / 3; i < n; i++) { + int key = rnd.nextInt(limit); + put(map, key); + } + } + + void mutateMap(NavigableMap map, int min, int max) { + int size = map.size(); + int rangeSize = max - min + 1; + + // Remove a bunch of entries directly + for (int i = 0, n = rangeSize / 2; i < n; i++) { + remove(map, min - 5 + rnd.nextInt(rangeSize + 10)); + } + + // Remove a bunch of entries with iterator + for (Iterator it = map.keySet().iterator(); it.hasNext(); ) { + if (rnd.nextBoolean()) { + bs.clear(it.next().value); + it.remove(); + } + } + + // Add entries till we're back to original size + while (map.size() < size) { + int key = min + rnd.nextInt(rangeSize); + assertTrue(key >= min && key <= max); + put(map, key); + } + } + + void mutateSubMap(NavigableMap map, int min, int max) { + int size = map.size(); + int rangeSize = max - min + 1; + + // Remove a bunch of entries directly + for (int i = 0, n = rangeSize / 2; i < n; i++) { + remove(map, min - 5 + rnd.nextInt(rangeSize + 10)); + } + + // Remove a bunch of entries with iterator + for (Iterator it = map.keySet().iterator(); it.hasNext(); ) { + if (rnd.nextBoolean()) { + bs.clear(it.next().value); + it.remove(); + } + } + + // Add entries till we're back to original size + while (map.size() < size) { + int key = min - 5 + rnd.nextInt(rangeSize + 10); + if (key >= min && key <= max) { + put(map, key); + } else { + try { + map.put(itemFor(key), itemFor(2 * key)); + shouldThrow(); + } catch (IllegalArgumentException success) {} + } + } + } + + void put(NavigableMap map, int key) { + if (map.put(itemFor(key), itemFor(2 * key)) == null) + bs.set(key); + } + + void remove(NavigableMap map, int key) { + if (map.remove(itemFor(key)) != null) + bs.clear(key); + } + + void bashSubMap(NavigableMap map, + int min, int max, boolean ascending) { + check(map, min, max, ascending); + check(map.descendingMap(), min, max, !ascending); + + mutateSubMap(map, min, max); + check(map, min, max, ascending); + check(map.descendingMap(), min, max, !ascending); + + // Recurse + if (max - min < 2) + return; + int midPoint = (min + max) / 2; + + // headMap - pick direction and endpoint inclusion randomly + boolean incl = rnd.nextBoolean(); + NavigableMap hm = map.headMap(itemFor(midPoint), incl); + if (ascending) { + if (rnd.nextBoolean()) + bashSubMap(hm, min, midPoint - (incl ? 0 : 1), true); + else + bashSubMap(hm.descendingMap(), min, midPoint - (incl ? 0 : 1), + false); + } else { + if (rnd.nextBoolean()) + bashSubMap(hm, midPoint + (incl ? 0 : 1), max, false); + else + bashSubMap(hm.descendingMap(), midPoint + (incl ? 0 : 1), max, + true); + } + + // tailMap - pick direction and endpoint inclusion randomly + incl = rnd.nextBoolean(); + NavigableMap tm = map.tailMap(itemFor(midPoint),incl); + if (ascending) { + if (rnd.nextBoolean()) + bashSubMap(tm, midPoint + (incl ? 0 : 1), max, true); + else + bashSubMap(tm.descendingMap(), midPoint + (incl ? 0 : 1), max, + false); + } else { + if (rnd.nextBoolean()) { + bashSubMap(tm, min, midPoint - (incl ? 0 : 1), false); + } else { + bashSubMap(tm.descendingMap(), min, midPoint - (incl ? 0 : 1), + true); + } + } + + // subMap - pick direction and endpoint inclusion randomly + int rangeSize = max - min + 1; + int[] endpoints = new int[2]; + endpoints[0] = min + rnd.nextInt(rangeSize); + endpoints[1] = min + rnd.nextInt(rangeSize); + Arrays.sort(endpoints); + boolean lowIncl = rnd.nextBoolean(); + boolean highIncl = rnd.nextBoolean(); + if (ascending) { + NavigableMap sm = map.subMap( + itemFor(endpoints[0]), lowIncl, itemFor(endpoints[1]), highIncl); + if (rnd.nextBoolean()) + bashSubMap(sm, endpoints[0] + (lowIncl ? 0 : 1), + endpoints[1] - (highIncl ? 0 : 1), true); + else + bashSubMap(sm.descendingMap(), endpoints[0] + (lowIncl ? 0 : 1), + endpoints[1] - (highIncl ? 0 : 1), false); + } else { + NavigableMap sm = map.subMap( + itemFor(endpoints[1]), highIncl, itemFor(endpoints[0]), lowIncl); + if (rnd.nextBoolean()) + bashSubMap(sm, endpoints[0] + (lowIncl ? 0 : 1), + endpoints[1] - (highIncl ? 0 : 1), false); + else + bashSubMap(sm.descendingMap(), endpoints[0] + (lowIncl ? 0 : 1), + endpoints[1] - (highIncl ? 0 : 1), true); + } + } + + /** + * min and max are both inclusive. If max < min, interval is empty. + */ + void check(NavigableMap map, + final int min, final int max, final boolean ascending) { + class ReferenceSet { + int lower(int key) { + return ascending ? lowerAscending(key) : higherAscending(key); + } + int floor(int key) { + return ascending ? floorAscending(key) : ceilingAscending(key); + } + int ceiling(int key) { + return ascending ? ceilingAscending(key) : floorAscending(key); + } + int higher(int key) { + return ascending ? higherAscending(key) : lowerAscending(key); + } + int first() { + return ascending ? firstAscending() : lastAscending(); + } + int last() { + return ascending ? lastAscending() : firstAscending(); + } + int lowerAscending(int key) { + return floorAscending(key - 1); + } + int floorAscending(int key) { + if (key < min) + return -1; + else if (key > max) + key = max; + + // BitSet should support this! Test would run much faster + while (key >= min) { + if (bs.get(key)) + return key; + key--; + } + return -1; + } + int ceilingAscending(int key) { + if (key < min) + key = min; + else if (key > max) + return -1; + int result = bs.nextSetBit(key); + return result > max ? -1 : result; + } + int higherAscending(int key) { + return ceilingAscending(key + 1); + } + private int firstAscending() { + int result = ceilingAscending(min); + return result > max ? -1 : result; + } + private int lastAscending() { + int result = floorAscending(max); + return result < min ? -1 : result; + } + } + ReferenceSet rs = new ReferenceSet(); + + // Test contents using containsKey + int size = 0; + for (int i = min; i <= max; i++) { + boolean bsContainsI = bs.get(i); + mustEqual(bsContainsI, map.containsKey(itemFor(i))); + if (bsContainsI) + size++; + } + mustEqual(size, map.size()); + + // Test contents using contains keySet iterator + int size2 = 0; + int previousKey = -1; + for (Item key : map.keySet()) { + assertTrue(bs.get(key.value)); + size2++; + assertTrue(previousKey < 0 || + (ascending ? key.value - previousKey > 0 : key.value - previousKey < 0)); + previousKey = key.value; + } + mustEqual(size2, size); + + // Test navigation ops + for (int key = min - 1; key <= max + 1; key++) { + Item k = itemFor(key); + assertEq(map.lowerKey(k), rs.lower(key)); + assertEq(map.floorKey(k), rs.floor(key)); + assertEq(map.higherKey(k), rs.higher(key)); + assertEq(map.ceilingKey(k), rs.ceiling(key)); + } + + // Test extrema + if (map.size() != 0) { + assertEq(map.firstKey(), rs.first()); + assertEq(map.lastKey(), rs.last()); + } else { + mustEqual(rs.first(), -1); + mustEqual(rs.last(), -1); + try { + map.firstKey(); + shouldThrow(); + } catch (NoSuchElementException success) {} + try { + map.lastKey(); + shouldThrow(); + } catch (NoSuchElementException success) {} + } + } + + static void assertEq(Item i, int j) { + if (i == null) + mustEqual(j, -1); + else + mustEqual(i, j); + } + + static boolean eq(Item i, int j) { + return i == null ? j == -1 : i.value == j; + } + }