blob: a7f8342d13282c4066ced97c2d38ff604ce0f187 [file] [log] [blame]
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.protobuf;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import junit.framework.TestCase;
/**
* @author darick@google.com Darick Tong
*/
public class SmallSortedMapTest extends TestCase {
// java.util.AbstractMap.SimpleEntry is private in JDK 1.5. We re-implement it
// here for JDK 1.5 users.
private static class SimpleEntry<K, V> implements Map.Entry<K, V> {
private final K key;
private V value;
SimpleEntry(K key, V value) {
this.key = key;
this.value = value;
}
@Override
public K getKey() {
return key;
}
@Override
public V getValue() {
return value;
}
@Override
public V setValue(V value) {
V oldValue = this.value;
this.value = value;
return oldValue;
}
private static boolean eq(Object o1, Object o2) {
return o1 == null ? o2 == null : o1.equals(o2);
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry e = (Map.Entry) o;
return eq(key, e.getKey()) && eq(value, e.getValue());
}
@Override
public int hashCode() {
return ((key == null) ? 0 : key.hashCode()) ^
((value == null) ? 0 : value.hashCode());
}
}
public void testPutAndGetArrayEntriesOnly() {
runPutAndGetTest(3);
}
public void testPutAndGetOverflowEntries() {
runPutAndGetTest(6);
}
private void runPutAndGetTest(int numElements) {
// Test with even and odd arraySize
SmallSortedMap<Integer, Integer> map1 =
SmallSortedMap.newInstanceForTest(3);
SmallSortedMap<Integer, Integer> map2 =
SmallSortedMap.newInstanceForTest(4);
SmallSortedMap<Integer, Integer> map3 =
SmallSortedMap.newInstanceForTest(3);
SmallSortedMap<Integer, Integer> map4 =
SmallSortedMap.newInstanceForTest(4);
// Test with puts in ascending order.
for (int i = 0; i < numElements; i++) {
assertNull(map1.put(i, i + 1));
assertNull(map2.put(i, i + 1));
}
// Test with puts in descending order.
for (int i = numElements - 1; i >= 0; i--) {
assertNull(map3.put(i, i + 1));
assertNull(map4.put(i, i + 1));
}
assertEquals(Math.min(3, numElements), map1.getNumArrayEntries());
assertEquals(Math.min(4, numElements), map2.getNumArrayEntries());
assertEquals(Math.min(3, numElements), map3.getNumArrayEntries());
assertEquals(Math.min(4, numElements), map4.getNumArrayEntries());
List<SmallSortedMap<Integer, Integer>> allMaps =
new ArrayList<SmallSortedMap<Integer, Integer>>();
allMaps.add(map1);
allMaps.add(map2);
allMaps.add(map3);
allMaps.add(map4);
for (SmallSortedMap<Integer, Integer> map : allMaps) {
assertEquals(numElements, map.size());
for (int i = 0; i < numElements; i++) {
assertEquals(new Integer(i + 1), map.get(i));
}
}
assertEquals(map1, map2);
assertEquals(map2, map3);
assertEquals(map3, map4);
}
public void testReplacingPut() {
SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
for (int i = 0; i < 6; i++) {
assertNull(map.put(i, i + 1));
assertNull(map.remove(i + 1));
}
for (int i = 0; i < 6; i++) {
assertEquals(new Integer(i + 1), map.put(i, i + 2));
}
}
public void testRemove() {
SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
for (int i = 0; i < 6; i++) {
assertNull(map.put(i, i + 1));
assertNull(map.remove(i + 1));
}
assertEquals(3, map.getNumArrayEntries());
assertEquals(3, map.getNumOverflowEntries());
assertEquals(6, map.size());
assertEquals(makeSortedKeySet(0, 1, 2, 3, 4, 5), map.keySet());
assertEquals(new Integer(2), map.remove(1));
assertEquals(3, map.getNumArrayEntries());
assertEquals(2, map.getNumOverflowEntries());
assertEquals(5, map.size());
assertEquals(makeSortedKeySet(0, 2, 3, 4, 5), map.keySet());
assertEquals(new Integer(5), map.remove(4));
assertEquals(3, map.getNumArrayEntries());
assertEquals(1, map.getNumOverflowEntries());
assertEquals(4, map.size());
assertEquals(makeSortedKeySet(0, 2, 3, 5), map.keySet());
assertEquals(new Integer(4), map.remove(3));
assertEquals(3, map.getNumArrayEntries());
assertEquals(0, map.getNumOverflowEntries());
assertEquals(3, map.size());
assertEquals(makeSortedKeySet(0, 2, 5), map.keySet());
assertNull(map.remove(3));
assertEquals(3, map.getNumArrayEntries());
assertEquals(0, map.getNumOverflowEntries());
assertEquals(3, map.size());
assertEquals(new Integer(1), map.remove(0));
assertEquals(2, map.getNumArrayEntries());
assertEquals(0, map.getNumOverflowEntries());
assertEquals(2, map.size());
}
public void testClear() {
SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
for (int i = 0; i < 6; i++) {
assertNull(map.put(i, i + 1));
}
map.clear();
assertEquals(0, map.getNumArrayEntries());
assertEquals(0, map.getNumOverflowEntries());
assertEquals(0, map.size());
}
public void testGetArrayEntryAndOverflowEntries() {
SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
for (int i = 0; i < 6; i++) {
assertNull(map.put(i, i + 1));
}
assertEquals(3, map.getNumArrayEntries());
for (int i = 0; i < 3; i++) {
Map.Entry<Integer, Integer> entry = map.getArrayEntryAt(i);
assertEquals(new Integer(i), entry.getKey());
assertEquals(new Integer(i + 1), entry.getValue());
}
Iterator<Map.Entry<Integer, Integer>> it =
map.getOverflowEntries().iterator();
for (int i = 3; i < 6; i++) {
assertTrue(it.hasNext());
Map.Entry<Integer, Integer> entry = it.next();
assertEquals(new Integer(i), entry.getKey());
assertEquals(new Integer(i + 1), entry.getValue());
}
assertFalse(it.hasNext());
}
public void testEntrySetContains() {
SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
for (int i = 0; i < 6; i++) {
assertNull(map.put(i, i + 1));
}
Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();
for (int i = 0; i < 6; i++) {
assertTrue(
entrySet.contains(new SimpleEntry<Integer, Integer>(i, i + 1)));
assertFalse(
entrySet.contains(new SimpleEntry<Integer, Integer>(i, i)));
}
}
public void testEntrySetAdd() {
SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();
for (int i = 0; i < 6; i++) {
Map.Entry<Integer, Integer> entry =
new SimpleEntry<Integer, Integer>(i, i + 1);
assertTrue(entrySet.add(entry));
assertFalse(entrySet.add(entry));
}
for (int i = 0; i < 6; i++) {
assertEquals(new Integer(i + 1), map.get(i));
}
assertEquals(3, map.getNumArrayEntries());
assertEquals(3, map.getNumOverflowEntries());
assertEquals(6, map.size());
}
public void testEntrySetRemove() {
SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();
for (int i = 0; i < 6; i++) {
assertNull(map.put(i, i + 1));
}
for (int i = 0; i < 6; i++) {
Map.Entry<Integer, Integer> entry =
new SimpleEntry<Integer, Integer>(i, i + 1);
assertTrue(entrySet.remove(entry));
assertFalse(entrySet.remove(entry));
}
assertTrue(map.isEmpty());
assertEquals(0, map.getNumArrayEntries());
assertEquals(0, map.getNumOverflowEntries());
assertEquals(0, map.size());
}
public void testEntrySetClear() {
SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
for (int i = 0; i < 6; i++) {
assertNull(map.put(i, i + 1));
}
map.entrySet().clear();
assertTrue(map.isEmpty());
assertEquals(0, map.getNumArrayEntries());
assertEquals(0, map.getNumOverflowEntries());
assertEquals(0, map.size());
}
public void testEntrySetIteratorNext() {
SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
for (int i = 0; i < 6; i++) {
assertNull(map.put(i, i + 1));
}
Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();
for (int i = 0; i < 6; i++) {
assertTrue(it.hasNext());
Map.Entry<Integer, Integer> entry = it.next();
assertEquals(new Integer(i), entry.getKey());
assertEquals(new Integer(i + 1), entry.getValue());
}
assertFalse(it.hasNext());
}
public void testEntrySetIteratorRemove() {
SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
for (int i = 0; i < 6; i++) {
assertNull(map.put(i, i + 1));
}
Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();
for (int i = 0; i < 6; i++) {
assertTrue(map.containsKey(i));
it.next();
it.remove();
assertFalse(map.containsKey(i));
assertEquals(6 - i - 1, map.size());
}
}
public void testMapEntryModification() {
SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
for (int i = 0; i < 6; i++) {
assertNull(map.put(i, i + 1));
}
Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();
for (int i = 0; i < 6; i++) {
Map.Entry<Integer, Integer> entry = it.next();
entry.setValue(i + 23);
}
for (int i = 0; i < 6; i++) {
assertEquals(new Integer(i + 23), map.get(i));
}
}
public void testMakeImmutable() {
SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
for (int i = 0; i < 6; i++) {
assertNull(map.put(i, i + 1));
}
map.makeImmutable();
assertEquals(new Integer(1), map.get(0));
assertEquals(6, map.size());
try {
map.put(23, 23);
fail("Expected UnsupportedOperationException");
} catch (UnsupportedOperationException expected) {
}
Map<Integer, Integer> other = new HashMap<Integer, Integer>();
other.put(23, 23);
try {
map.putAll(other);
fail("Expected UnsupportedOperationException");
} catch (UnsupportedOperationException expected) {
}
try {
map.remove(0);
fail("Expected UnsupportedOperationException");
} catch (UnsupportedOperationException expected) {
}
try {
map.clear();
fail("Expected UnsupportedOperationException");
} catch (UnsupportedOperationException expected) {
}
Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();
try {
entrySet.clear();
fail("Expected UnsupportedOperationException");
} catch (UnsupportedOperationException expected) {
}
Iterator<Map.Entry<Integer, Integer>> it = entrySet.iterator();
while (it.hasNext()) {
Map.Entry<Integer, Integer> entry = it.next();
try {
entry.setValue(0);
fail("Expected UnsupportedOperationException");
} catch (UnsupportedOperationException expected) {
}
try {
it.remove();
fail("Expected UnsupportedOperationException");
} catch (UnsupportedOperationException expected) {
}
}
Set<Integer> keySet = map.keySet();
try {
keySet.clear();
fail("Expected UnsupportedOperationException");
} catch (UnsupportedOperationException expected) {
}
Iterator<Integer> keys = keySet.iterator();
while (keys.hasNext()) {
Integer key = keys.next();
try {
keySet.remove(key);
fail("Expected UnsupportedOperationException");
} catch (UnsupportedOperationException expected) {
}
try {
keys.remove();
fail("Expected UnsupportedOperationException");
} catch (UnsupportedOperationException expected) {
}
}
}
private Set<Integer> makeSortedKeySet(Integer... keys) {
return new TreeSet<Integer>(Arrays.<Integer>asList(keys));
}
}