| /* |
| * 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"); |
| } |
| } |