/* * Copyright 2013 Samppa Saarela * * Licensed 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.javersion.util; import static com.google.common.collect.Iterables.transform; import static org.hamcrest.Matchers.*; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.javersion.util.AbstractRedBlackTree.Color; import org.javersion.util.AbstractTreeMap.Node; import org.junit.Test; public class PersistentTreeMapTest extends AbstractPersistentMapTest<PersistentTreeMap<Integer, Integer>> { @Test public void Iterate_Random() { PersistentTreeMap<Integer, Integer> map = emptyMap(); for (Integer kv : randoms(1234)) { map = map.assoc(kv, kv); } Iterator<Map.Entry<Integer, Integer>> iter = map.iterator(); int count = 0; Integer prev = null; Integer next; while (iter.hasNext()) { count++; if (prev == null) { prev = iter.next().getKey(); } else { next = iter.next().getKey(); assertThat(prev, lessThan(next)); prev = next; } } assertThat(count, equalTo(1234)); } @Test public void Iterate_Ascending() { PersistentTreeMap<Integer, Integer> pmap = emptyMap(); for (int kv = 1; kv < 10; kv++) { pmap = pmap.assoc(kv, kv); } assertThat(keys(pmap), contains(1, 2, 3, 4, 5, 6, 7, 8, 9)); } @Test public void Iterate_Descending() { PersistentTreeMap<Integer, Integer> pmap = emptyMap(); for (int kv = 1; kv < 10; kv++) { pmap = pmap.assoc(kv, kv); } final PersistentTreeMap<Integer, Integer> map = pmap; assertThat(keys(new Iterable<Map.Entry<Integer, Integer>>() { @Override public Iterator<Entry<Integer, Integer>> iterator() { return map.iterator(false); } }), contains(1, 2, 3, 4, 5, 6, 7, 8, 9)); } @Test public void Iterate_Ascending_Range() { PersistentTreeMap<Integer, Integer> map = mapForRangeTest(); assertThat(keys(map.range(3, 9)), contains(3, 5, 7)); assertThat(keys(map.range(3, true, 9, true)), contains(3, 5, 7, 9)); assertThat(keys(map.range(3, false, 9, false)), contains(5, 7)); assertThat(keys(map.range(9, 10)), contains(9)); assertThat(keys(map.range(-5, 2)), contains(1)); assertThat(keys(map.range(6, 7)), emptyIterable()); assertThat(keys(map.range(-10, 1)), emptyIterable()); assertThat(keys(map.range(9, false, 20, false)), emptyIterable()); } private PersistentTreeMap<Integer, Integer> mapForRangeTest() { PersistentTreeMap<Integer, Integer> map = emptyMap(); for (int kv = 1; kv < 10; kv += 2) { map = map.assoc(kv, kv); } return map; } @Test public void Iterate_Descending_Range() { PersistentTreeMap<Integer, Integer> map = mapForRangeTest(); assertThat(keys(map.range(3, true, 9, false, false)), contains(7, 5, 3)); assertThat(keys(map.range(3, true, 9, true, false)), contains(9, 7, 5, 3)); assertThat(keys(map.range(3, false, 9, false, false)), contains(7, 5)); } @Test public void Iterate_Ascending_Tail_Map() { PersistentTreeMap<Integer, Integer> map = mapForRangeTest(); assertThat(keys(map.range(7, true, null, false, true)), contains(7, 9)); } @Test public void Iterate_Descending_Tail_Map() { PersistentTreeMap<Integer, Integer> map = mapForRangeTest(); assertThat(keys(map.range(7, true, null, false, false)), contains(9, 7)); } @Test public void Iterate_Ascending_Head_Map() { PersistentTreeMap<Integer, Integer> map = mapForRangeTest(); assertThat(keys(map.range(null, true, 5, true, true)), contains(1, 3, 5)); assertThat(keys(map.range(null, true, 5, false, true)), contains(1, 3)); } @Test public void Iterate_Descending_Head_Map() { PersistentTreeMap<Integer, Integer> map = mapForRangeTest(); assertThat(keys(map.range(null, true, 5, true, false)), contains(5, 3, 1)); assertThat(keys(map.range(null, true, 5, false, false)), contains(3, 1)); } private static Iterable<Integer> keys(Iterable<Map.Entry<Integer, Integer>> entries) { return transform(entries, MapUtils.<Integer>mapKeyFunction()); } @Test public void CLR_P269() { // Example tree assertInsert( 11, 2, 14, 1, 7, 15, 5, 8, 4 ); // Same nodes in ascending order assertInsert( 1, 2, 4, 5, 7, 8, 11, 14, 15 ); } @Test public void floor() { PersistentTreeMap<Integer, Integer> map = mapForRangeTest(); assertThat(map.floorEntry(0), nullValue()); assertThat(map.floorEntry(1).getKey(), equalTo(1)); assertThat(map.floorEntry(2).getKey(), equalTo(1)); assertThat(map.floorEntry(3).getKey(), equalTo(3)); assertThat(map.floorEntry(4).getKey(), equalTo(3)); assertThat(map.floorEntry(5).getKey(), equalTo(5)); assertThat(map.floorEntry(6).getKey(), equalTo(5)); assertThat(map.floorEntry(7).getKey(), equalTo(7)); assertThat(map.floorEntry(8).getKey(), equalTo(7)); assertThat(map.floorEntry(9).getKey(), equalTo(9)); assertThat(map.floorEntry(10).getKey(), equalTo(9)); assertThat(map.floorEntry(11).getKey(), equalTo(9)); } @Test public void lower() { PersistentTreeMap<Integer, Integer> map = mapForRangeTest(); assertThat(map.lowerEntry(0), nullValue()); assertThat(map.lowerEntry(1), nullValue()); assertThat(map.lowerEntry(2).getKey(), equalTo(1)); assertThat(map.lowerEntry(3).getKey(), equalTo(1)); assertThat(map.lowerEntry(4).getKey(), equalTo(3)); assertThat(map.lowerEntry(5).getKey(), equalTo(3)); assertThat(map.lowerEntry(6).getKey(), equalTo(5)); assertThat(map.lowerEntry(7).getKey(), equalTo(5)); assertThat(map.lowerEntry(8).getKey(), equalTo(7)); assertThat(map.lowerEntry(9).getKey(), equalTo(7)); assertThat(map.lowerEntry(10).getKey(), equalTo(9)); assertThat(map.lowerEntry(11).getKey(), equalTo(9)); } @Test public void ceiling() { PersistentTreeMap<Integer, Integer> map = mapForRangeTest(); assertThat(map.ceilingEntry(0).getKey(), equalTo(1)); assertThat(map.ceilingEntry(1).getKey(), equalTo(1)); assertThat(map.ceilingEntry(2).getKey(), equalTo(3)); assertThat(map.ceilingEntry(3).getKey(), equalTo(3)); assertThat(map.ceilingEntry(4).getKey(), equalTo(5)); assertThat(map.ceilingEntry(5).getKey(), equalTo(5)); assertThat(map.ceilingEntry(6).getKey(), equalTo(7)); assertThat(map.ceilingEntry(7).getKey(), equalTo(7)); assertThat(map.ceilingEntry(8).getKey(), equalTo(9)); assertThat(map.ceilingEntry(9).getKey(), equalTo(9)); assertThat(map.ceilingEntry(10), nullValue()); } @Test public void higher() { PersistentTreeMap<Integer, Integer> map = mapForRangeTest(); assertThat(map.higherEntry(0).getKey(), equalTo(1)); assertThat(map.higherEntry(1).getKey(), equalTo(3)); assertThat(map.higherEntry(2).getKey(), equalTo(3)); assertThat(map.higherEntry(3).getKey(), equalTo(5)); assertThat(map.higherEntry(4).getKey(), equalTo(5)); assertThat(map.higherEntry(5).getKey(), equalTo(7)); assertThat(map.higherEntry(6).getKey(), equalTo(7)); assertThat(map.higherEntry(7).getKey(), equalTo(9)); assertThat(map.higherEntry(8).getKey(), equalTo(9)); assertThat(map.higherEntry(9), nullValue()); assertThat(map.higherEntry(10), nullValue()); } @Test public void first_last() { PersistentTreeMap<Integer, Integer> map = mapForRangeTest(); assertThat(map.getFirstEntry().getKey(), equalTo(1)); assertThat(map.getLastEntry().getKey(), equalTo(9)); } @Test public void Find_Min_Max() { List<Integer> ints = ascending(37); PersistentTreeMap<Integer, Integer> pmap = emptyMap(); for (Integer kv : ints) { pmap = pmap.assoc(kv, kv); } assertThat(pmap.max(), equalTo(ints.get(36))); assertThat(pmap.min(), equalTo(ints.get(0))); } @Test public void Find_Min_Max_From_Empty() { PersistentTreeMap<Integer, Integer> pmap = emptyMap(); assertThat(pmap.max(), nullValue()); assertThat(pmap.min(), nullValue()); } private static Integer blacksOnPath = null; static synchronized void assertNodeProperties(Node<Integer, Integer> node) { blacksOnPath = null; if (node != null) { assertNodeProperties(node, 0); } } private static void assertNodeProperties(Node<Integer, Integer> node, int blacks) { assertThat(node.color, not(nullValue())); if (node.color == Color.RED) { assertBlack(node.left); assertBlack(node.right); } else { blacks++; } boolean leaf = true; if (node.left != null){ assertThat(node.left.key, lessThan(node.key)); assertNodeProperties(node.left, blacks); leaf = false; } if (node.right != null) { assertThat(node.right.key, greaterThan(node.key)); assertNodeProperties(node.right, blacks); leaf = false; } if (leaf) { if (blacksOnPath == null) { blacksOnPath = blacks; } else { assertThat(blacks, equalTo(blacksOnPath.intValue())); } } } static void assertBlack(Node<?, ?> node) { assertTrue("Expected black node (or null)", node == null || node.color == Color.BLACK); } @Override protected PersistentTreeMap<Integer, Integer> emptyMap() { return PersistentTreeMap.<Integer, Integer>empty(); } @Override protected void assertMapProperties(PersistentMap<Integer, Integer> map) { assertNodeProperties(((PersistentTreeMap<Integer, Integer>) map).root()); } @Override protected void assertEmptyMap(PersistentMap<Integer, Integer> map) { assertThat(map.size(), equalTo(0)); assertThat(((PersistentTreeMap<Integer, Integer>) map).root(), nullValue()); } }