blob: 8662a4825eeab5002b08b28fa98167e20ffad29b [file] [log] [blame]
/*
* 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.ignite.lang.utils;
import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import org.apache.ignite.internal.util.GridLeanMap;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.apache.ignite.testframework.junits.common.GridCommonTest;
import org.jetbrains.annotations.Nullable;
import org.junit.Test;
/**
* Tests for {@link GridLeanMap}.
*/
@GridCommonTest(group = "Lang")
public class GridLeanMapSelfTest extends GridCommonAbstractTest {
/**
* JUnit.
*
* @throws Exception If failed.
*/
@Test
public void testDefaultMap() throws Exception {
Map<String, String> map = new GridLeanMap<>();
checkEmptyMap(map);
checkImpl(map, "Map3");
try {
map.keySet().iterator().next();
fail("NoSuchElementException must have been thrown.");
}
catch (NoSuchElementException e) {
info("Caught expected exception: " + e);
}
try {
map.entrySet().iterator().next();
fail("NoSuchElementException must have been thrown.");
}
catch (NoSuchElementException e) {
info("Caught expected exception: " + e);
}
try {
map.values().iterator().next();
fail("NoSuchElementException must have been thrown.");
}
catch (NoSuchElementException e) {
info("Caught expected exception: " + e);
}
try {
map.keySet().iterator().remove();
fail("IllegalStateException must have been thrown.");
}
catch (IllegalStateException e) {
info("Caught expected exception: " + e);
}
try {
map.entrySet().iterator().remove();
fail("IllegalStateException must have been thrown.");
}
catch (IllegalStateException e) {
info("Caught expected exception: " + e);
}
try {
map.values().iterator().remove();
fail("IllegalStateException must have been thrown.");
}
catch (IllegalStateException e) {
info("Caught expected exception: " + e);
}
}
/**
* JUnit.
*
* @throws Exception If failed.
*/
@Test
public void testEmptyMap() throws Exception {
Map<String, String> map = new GridLeanMap<>(0);
checkEmptyMap(map);
checkImplBySize(map);
try {
map.keySet().iterator().next();
fail("NoSuchElementException must have been thrown.");
}
catch (NoSuchElementException e) {
info("Caught expected exception: " + e);
}
try {
map.entrySet().iterator().next();
fail("NoSuchElementException must have been thrown.");
}
catch (NoSuchElementException e) {
info("Caught expected exception: " + e);
}
try {
map.values().iterator().next();
fail("NoSuchElementException must have been thrown.");
}
catch (NoSuchElementException e) {
info("Caught expected exception: " + e);
}
try {
map.keySet().iterator().remove();
fail("IllegalStateException must have been thrown.");
}
catch (IllegalStateException e) {
info("Caught expected exception: " + e);
}
try {
map.entrySet().iterator().remove();
fail("IllegalStateException must have been thrown.");
}
catch (IllegalStateException e) {
info("Caught expected exception: " + e);
}
try {
map.values().iterator().remove();
fail("IllegalStateException must have been thrown.");
}
catch (IllegalStateException e) {
info("Caught expected exception: " + e);
}
}
/**
* JUnit.
*
* @throws Exception If failed.
*/
@Test
public void testOneEntryMap() throws Exception {
Map<String, String> map = new GridLeanMap<>(0);
map.put("k1", "v1");
checkImplBySize(map);
assert !map.isEmpty();
assertEquals(1, map.size());
assert map.containsKey("k1");
assert map.containsValue("v1");
assert !map.keySet().isEmpty();
assert !map.entrySet().isEmpty();
assert !map.values().isEmpty();
assertEquals("v1", map.get("k1"));
assert map.get("k2") == null;
Iterator<String> kIter = map.keySet().iterator();
assertEquals("k1", kIter.next());
assert !kIter.hasNext();
Iterator<Map.Entry<String, String>> eIter = map.entrySet().iterator();
Map.Entry<String, String> entry = eIter.next();
assert entry != null;
assertEquals("k1", entry.getKey());
assertEquals("v1", entry.getValue());
assert !eIter.hasNext();
Iterator<String> vIter = map.values().iterator();
assertEquals("v1", vIter.next());
assert !vIter.hasNext();
}
/**
* JUnit.
*
* @throws Exception If failed.
*/
@Test
public void testMapPutSameKey() throws Exception {
Map<String, String> map = new GridLeanMap<>(0);
map.put("k1", "v1");
map.put("k1", "v2");
checkImplBySize(map);
assertEquals(1, map.size());
assertEquals("v2", map.get("k1"));
}
/**
* JUnit.
*
* @throws Exception If failed.
*/
@Test
public void testMultipleEntriesMap() throws Exception {
Map<String, String> map = new GridLeanMap<>(0);
map.put("k1", "v1");
checkImplBySize(map);
map.put("k2", "v2");
checkImplBySize(map);
map.put("k3", "v3");
checkImplBySize(map);
map.put("k4", "v4");
checkImplBySize(map);
map.put("k5", "v5");
checkImplBySize(map);
map.put("k6", "v6");
assert !map.isEmpty();
assertEquals(6, map.size());
assert map.containsKey("k1");
assert map.containsKey("k2");
assert map.containsKey("k3");
assert map.containsKey("k4");
assert map.containsKey("k5");
assert map.containsKey("k6");
assert map.containsValue("v1");
assert map.containsValue("v2");
assert map.containsValue("v3");
assert map.containsValue("v4");
assert map.containsValue("v5");
assert map.containsValue("v6");
assert !map.keySet().isEmpty();
assert !map.entrySet().isEmpty();
assert !map.values().isEmpty();
assertEquals("v1", map.get("k1"));
assertEquals("v2", map.get("k2"));
assertEquals("v3", map.get("k3"));
assertEquals("v4", map.get("k4"));
assertEquals("v5", map.get("k5"));
assertEquals("v6", map.get("k6"));
assert map.get("k7") == null;
Iterator<String> kIter = map.keySet().iterator();
for (int i = 0; i < 6; i++)
assert kIter.next().contains("k");
assert !kIter.hasNext();
Iterator<Map.Entry<String, String>> eIter = map.entrySet().iterator();
for (int i = 0; i < 6; i++) {
Map.Entry<String, String> entry = eIter.next();
assert entry != null : "Empty entry number: " + i;
assert entry.getKey().contains("k") : "Invalid entry number: " + i;
assert entry.getValue().contains("v") : "Invalid entry number: " + i;
}
assert !eIter.hasNext();
Iterator<String> vIter = map.values().iterator();
for (int i = 0; i < 6; i++)
assert vIter.next().contains("v");
assert !vIter.hasNext();
}
/**
* JUnit.
*
* @throws Exception If failed.
*/
@Test
public void testMapRemove() throws Exception {
Map<String, String> map = new GridLeanMap<>(0);
// Put 1 entry.
map.put("k1", "v1");
checkImpl(map, "Map1");
assertEquals("v1", map.remove("k1"));
checkEmptyMap(map);
checkImpl(map, null);
// Put 2 entries.
map.put("k1", "v1");
map.put("k2", "v2");
checkImpl(map, "Map2");
assertEquals("v1", map.remove("k1"));
assertEquals("v2", map.remove("k2"));
checkEmptyMap(map);
checkImpl(map, null);
// Put more than 5 entries.
map.put("k1", "v1");
map.put("k2", "v2");
map.put("k3", "v3");
map.put("k4", "v4");
map.put("k5", "v5");
map.put("k6", "v6");
map.put("k7", "v7");
checkImpl(map, "LeanHashMap");
checkImplBySize(map);
assertEquals("v1", map.remove("k1"));
assertEquals("v2", map.remove("k2"));
assertEquals("v3", map.remove("k3"));
assertEquals("v4", map.remove("k4"));
assertEquals("v5", map.remove("k5"));
assertEquals("v6", map.remove("k6"));
assertEquals("v7", map.remove("k7"));
checkEmptyMap(map);
checkImpl(map, null);
}
/**
* JUnit.
*
* @throws Exception If failed.
*/
@Test
public void testMapClear() throws Exception {
Map<String, String> map = new GridLeanMap<>();
map.put("k1", "v1");
map.put("k2", "v2");
map.put("k3", "v3");
map.put("k4", "v4");
map.put("k5", "v5");
map.put("k6", "v6");
map.clear();
checkEmptyMap(map);
checkImplBySize(map);
}
/**
* JUnit.
*
* @throws Exception If failed.
*/
@Test
public void testEntrySet() throws Exception {
Map<String, String> map = new GridLeanMap<>();
map.put("k1", "v1");
map.put("k2", "v2");
map.put("k3", "v3");
map.put("k4", "v4");
map.put("k5", "v5");
map.put("k6", "v6");
checkImpl(map, "LeanHashMap");
Iterator<Map.Entry<String, String>> iter = map.entrySet().iterator();
assert iter.hasNext();
Map.Entry<String, String> e = iter.next();
assert e.getKey().contains("k");
assert e.getValue().contains("v");
iter.next();
iter.remove();
checkImpl(map, "Map5");
assertEquals(5, map.size());
assert iter.next() != null;
assert iter.next() != null;
iter.remove();
checkImpl(map, "Map4");
assertEquals(4, map.size());
assert iter.next() != null;
assert iter.hasNext();
assert iter.next() != null;
assert !iter.hasNext();
}
/**
* JUnit.
*
* @throws Exception If failed.
*/
@Test
public void testWithInitSize1() throws Exception {
// Batch mode.
Map<String, String> map = new GridLeanMap<>(4);
checkEmptyMap(map);
checkImpl(map, "Map4");
map.put("k1", "v1");
assertEquals(1, map.size());
checkImpl(map, "Map4");
map.put("k2", "v2");
assertEquals(2, map.size());
checkImpl(map, "Map4");
// The same key does not lead to implementation change.
map.put("k2", "v2");
assertEquals(2, map.size());
checkImpl(map, "Map4");
map.put("k3", "v3");
assertEquals(3, map.size());
checkImpl(map, "Map4");
map.put("k4", "v4");
assertEquals(4, map.size());
checkImpl(map, "Map4");
map.put("k5", "v5");
assertEquals(5, map.size());
checkImpl(map, "Map5");
map.put("k6", "v6");
assertEquals(6, map.size());
checkImpl(map, "LeanHashMap");
map = new GridLeanMap<>(4);
checkEmptyMap(map);
checkImpl(map, "Map4");
map.put("k1", "v1");
assertEquals(1, map.size());
checkImpl(map, "Map4");
map.put("k2", "v2");
assertEquals(2, map.size());
checkImpl(map, "Map4");
// Any remove operation leads to map size optimization.
assertEquals("v1", map.remove("k1"));
checkImpl(map, "Map1");
}
/**
* JUnit.
*
* @throws Exception If failed.
*/
@Test
public void testWithInitSize2() throws Exception {
// Batch mode.
Map<String, String> map = new GridLeanMap<>(10);
checkEmptyMap(map);
checkImpl(map, "LeanHashMap");
map.put("k1", "v1");
assertEquals(1, map.size());
checkImpl(map, "LeanHashMap");
map.put("k2", "v2");
assertEquals(2, map.size());
checkImpl(map, "LeanHashMap");
map.put("k3", "v3");
assertEquals(3, map.size());
checkImpl(map, "LeanHashMap");
map.put("k4", "v4");
assertEquals(4, map.size());
checkImpl(map, "LeanHashMap");
map.put("k5", "v5");
assertEquals(5, map.size());
checkImpl(map, "LeanHashMap");
map.put("k6", "v6");
assertEquals(6, map.size());
checkImpl(map, "LeanHashMap");
map.put("k7", "v7");
assertEquals(7, map.size());
checkImpl(map, "LeanHashMap");
map.put("k8", "v8");
assertEquals(8, map.size());
checkImpl(map, "LeanHashMap");
map.put("k9", "v9");
assertEquals(9, map.size());
checkImpl(map, "LeanHashMap");
map.put("k10", "v10");
assertEquals(10, map.size());
checkImpl(map, "LeanHashMap");
}
/**
* Checks map emptiness.
*
* @param map Map to check.
* @throws Exception If failed.
*/
private void checkEmptyMap(Map<?, ?> map) throws Exception {
assert map.isEmpty();
assert !map.containsKey("key");
assert !map.containsValue("value");
assertEquals(0, map.size());
assert map.keySet().isEmpty();
assert map.entrySet().isEmpty();
assert map.values().isEmpty();
assert !map.keySet().iterator().hasNext();
assert !map.entrySet().iterator().hasNext();
assert !map.values().iterator().hasNext();
}
/**
* @param map Lean map.
* @param implName Internal implementation simple class name.
* {@code null} for empty implementation.
* @throws Exception If failed.
*/
private void checkImpl(Map map, @Nullable String implName) throws Exception {
assert map != null;
Field f = GridLeanMap.class.getDeclaredField("map");
f.setAccessible(true);
Map impl = (Map)f.get(map);
if (implName != null)
assertEquals(implName, impl.getClass().getSimpleName());
else
assert impl == null;
}
/**
* @param map Lean map.
* @throws Exception If failed.
*/
private void checkImplBySize(Map map) throws Exception {
assert map != null;
if (map.isEmpty())
checkImpl(map, null);
else if (map.size() == 1)
checkImpl(map, "Map1");
else if (map.size() == 2)
checkImpl(map, "Map2");
else if (map.size() == 3)
checkImpl(map, "Map3");
else if (map.size() == 4)
checkImpl(map, "Map4");
else if (map.size() == 5)
checkImpl(map, "Map5");
else
checkImpl(map, "LeanHashMap");
}
}