/*
* Original work Copyright 2015 Real Logic Ltd.
* Modified work Copyright (c) 2015, Hazelcast, Inc. All Rights Reserved.
*
* 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 com.hazelcast.util.collection;
import com.hazelcast.test.HazelcastParallelClassRunner;
import com.hazelcast.test.annotation.ParallelTest;
import com.hazelcast.test.annotation.QuickTest;
import org.junit.Assert;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import static java.lang.Long.valueOf;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.hamcrest.number.IsCloseTo.closeTo;
import static org.hamcrest.number.OrderingComparison.lessThan;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
@RunWith(HazelcastParallelClassRunner.class)
@Category({QuickTest.class, ParallelTest.class})
public class Long2ObjectHashMapTest {
private final Long2ObjectHashMap<String> longToObjectMap = new Long2ObjectHashMap<String>();
@Test
public void shouldDoPutAndThenGet() {
final String value = "Seven";
longToObjectMap.put(7, value);
assertThat(longToObjectMap.get(7), is(value));
}
@Test
public void shouldReplaceExistingValueForTheSameKey() {
final long key = 7;
final String value = "Seven";
longToObjectMap.put(key, value);
final String newValue = "New Seven";
final String oldValue = longToObjectMap.put(key, newValue);
assertThat(longToObjectMap.get(key), is(newValue));
assertThat(oldValue, is(value));
assertThat(valueOf(longToObjectMap.size()), is(valueOf(1)));
}
@Test
public void shouldGrowWhenThresholdExceeded() {
final double loadFactor = 0.5d;
final Long2ObjectHashMap<String> map = new Long2ObjectHashMap<String>(32, loadFactor);
for (int i = 0; i < 16; i++) {
map.put(i, Long.toString(i));
}
assertThat(valueOf(map.resizeThreshold()), is(valueOf(16)));
assertThat(valueOf(map.capacity()), is(valueOf(32)));
assertThat(valueOf(map.size()), is(valueOf(16)));
map.put(16, "16");
assertThat(valueOf(map.resizeThreshold()), is(valueOf(32)));
assertThat(valueOf(map.capacity()), is(valueOf(64)));
assertThat(valueOf(map.size()), is(valueOf(17)));
assertThat(map.get(16), equalTo("16"));
assertThat(loadFactor, closeTo(map.loadFactor(), 0.0));
}
@Test
public void shouldHandleCollisionAndThenLinearProbe() {
final double loadFactor = 0.5d;
final Long2ObjectHashMap<String> map = new Long2ObjectHashMap<String>(32, loadFactor);
final long key = 7;
final String value = "Seven";
map.put(key, value);
final long collisionKey = key + map.capacity();
final String collisionValue = Long.toString(collisionKey);
map.put(collisionKey, collisionValue);
assertThat(map.get(key), is(value));
assertThat(map.get(collisionKey), is(collisionValue));
assertThat(loadFactor, closeTo(map.loadFactor(), 0.0));
}
@Test
public void shouldClearCollection() {
for (int i = 0; i < 15; i++) {
longToObjectMap.put(i, Long.toString(i));
}
assertThat(valueOf(longToObjectMap.size()), is(valueOf(15)));
assertThat(longToObjectMap.get(1), is("1"));
longToObjectMap.clear();
assertThat(valueOf(longToObjectMap.size()), is(valueOf(0)));
Assert.assertNull(longToObjectMap.get(1));
}
@Test
public void shouldCompactCollection() {
final int totalItems = 50;
for (int i = 0; i < totalItems; i++) {
longToObjectMap.put(i, Long.toString(i));
}
for (int i = 0, limit = totalItems - 4; i < limit; i++) {
longToObjectMap.remove(i);
}
final int capacityBeforeCompaction = longToObjectMap.capacity();
longToObjectMap.compact();
assertThat(valueOf(longToObjectMap.capacity()), lessThan(valueOf(capacityBeforeCompaction)));
}
@Test
public void shouldContainValue() {
final long key = 7;
final String value = "Seven";
longToObjectMap.put(key, value);
Assert.assertTrue(longToObjectMap.containsValue(value));
Assert.assertFalse(longToObjectMap.containsValue("NoKey"));
}
@Test
public void shouldContainKey() {
final long key = 7;
final String value = "Seven";
longToObjectMap.put(key, value);
Assert.assertTrue(longToObjectMap.containsKey(key));
Assert.assertFalse(longToObjectMap.containsKey(0));
}
@Test
public void shouldRemoveEntry() {
final long key = 7;
final String value = "Seven";
longToObjectMap.put(key, value);
Assert.assertTrue(longToObjectMap.containsKey(key));
longToObjectMap.remove(key);
Assert.assertFalse(longToObjectMap.containsKey(key));
}
@Test
public void shouldRemoveEntryAndCompactCollisionChain() {
final long key = 12;
final String value = "12";
longToObjectMap.put(key, value);
longToObjectMap.put(13, "13");
final long collisionKey = key + longToObjectMap.capacity();
final String collisionValue = Long.toString(collisionKey);
longToObjectMap.put(collisionKey, collisionValue);
longToObjectMap.put(14, "14");
assertThat(longToObjectMap.remove(key), is(value));
}
@Test
public void shouldIterateValues() {
final Collection<String> initialSet = new HashSet<String>();
for (int i = 0; i < 11; i++) {
final String value = Long.toString(i);
longToObjectMap.put(i, value);
initialSet.add(value);
}
final Collection<String> copyToSet = new HashSet<String>(longToObjectMap.values());
assertThat(copyToSet, is(initialSet));
}
@Test
public void shouldIterateKeysGettingLongAsPrimitive() {
final Collection<Long> initialSet = new HashSet<Long>();
for (int i = 0; i < 11; i++) {
final String value = Long.toString(i);
longToObjectMap.put(i, value);
initialSet.add(valueOf(i));
}
final Collection<Long> copyToSet = new HashSet<Long>();
for (final Long2ObjectHashMap.KeyIterator iter = longToObjectMap.keySet().iterator(); iter.hasNext(); ) {
copyToSet.add(valueOf(iter.nextLong()));
}
assertThat(copyToSet, is(initialSet));
}
@Test
public void shouldIterateKeys() {
final Collection<Long> initialSet = new HashSet<Long>();
for (int i = 0; i < 11; i++) {
final String value = Long.toString(i);
longToObjectMap.put(i, value);
initialSet.add(valueOf(i));
}
final Collection<Long> copyToSet = new HashSet<Long>(longToObjectMap.keySet());
assertThat(copyToSet, is(initialSet));
}
@Test
public void shouldIterateAndHandleRemove() {
final Collection<Long> initialSet = new HashSet<Long>();
final int count = 11;
for (int i = 0; i < count; i++) {
final String value = Long.toString(i);
longToObjectMap.put(i, value);
initialSet.add(valueOf(i));
}
final Collection<Long> copyOfSet = new HashSet<Long>();
int i = 0;
for (final Iterator<Long> iter = longToObjectMap.keySet().iterator(); iter.hasNext(); ) {
final Long item = iter.next();
if (i++ == 7) {
iter.remove();
} else {
copyOfSet.add(item);
}
}
assertThat(valueOf(initialSet.size()), is(valueOf(count)));
final int reducedSetSize = count - 1;
assertThat(valueOf(longToObjectMap.size()), is(valueOf(reducedSetSize)));
assertThat(valueOf(copyOfSet.size()), is(valueOf(reducedSetSize)));
}
@Test
public void shouldIterateEntries() {
final int count = 11;
for (int i = 0; i < count; i++) {
final String value = Long.toString(i);
longToObjectMap.put(i, value);
}
final String testValue = "Wibble";
for (final Map.Entry<Long, String> entry : longToObjectMap.entrySet()) {
assertThat(entry.getKey(), equalTo(valueOf(entry.getValue())));
if (entry.getKey().intValue() == 7) {
entry.setValue(testValue);
}
}
assertThat(longToObjectMap.get(7), equalTo(testValue));
}
@Test
public void shouldGenerateStringRepresentation() {
final int[] testEntries = {3, 1, 19, 7, 11, 12, 7};
for (final int testEntry : testEntries) {
longToObjectMap.put(testEntry, String.valueOf(testEntry));
}
final String mapAsAString = "{11=11, 7=7, 3=3, 12=12, 19=19, 1=1}";
assertThat(longToObjectMap.toString(), equalTo(mapAsAString));
}
@Test
public void sizeShouldReturnNumberOfEntries() {
final int count = 100;
for (int key = 0; key < count; key++) {
longToObjectMap.put(key, "value");
}
assertEquals(count, longToObjectMap.size());
}
}