/* * Copyright (c) 2008-2017, 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.internal.util.collection; import com.hazelcast.internal.memory.impl.HeapMemoryManager; import com.hazelcast.test.HazelcastParallelClassRunner; import com.hazelcast.test.RequireAssertEnabled; import com.hazelcast.test.annotation.QuickTest; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import java.util.Random; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @RunWith(HazelcastParallelClassRunner.class) @Category(QuickTest.class) public class Long2LongMapHsaTest { private static final long MISSING_VALUE = -1L; private final Random random = new Random(); private HeapMemoryManager memMgr; private Long2LongMapHsa map; @Before public void setUp() throws Exception { memMgr = new HeapMemoryManager(2 * 1000 * 1000); map = new Long2LongMapHsa(MISSING_VALUE, memMgr); } @After public void tearDown() throws Exception { map.dispose(); memMgr.dispose(); } @Test public void testPut() { long key = newKey(); long value = newValue(); assertEqualsKV(MISSING_VALUE, map.put(key, value), key, value); long newValue = newValue(); long oldValue = map.put(key, newValue); assertEqualsKV(value, oldValue, key, value); } @Test public void testGet() { long key = newKey(); long value = newValue(); map.put(key, value); long currentValue = map.get(key); assertEqualsKV(value, currentValue, key, value); } @Test public void testPutIfAbsent_success() { long key = newKey(); long value = newValue(); assertEqualsKV(MISSING_VALUE, map.putIfAbsent(key, value), key, value); } @Test public void testPutIfAbsent_fail() { long key = newKey(); long value = newValue(); map.put(key, value); long newValue = newValue(); assertEqualsKV(value, map.putIfAbsent(key, newValue), key, value); } @Test public void testPutAll() throws Exception { int count = 100; Long2LongMap entries = new Long2LongMapHsa(count, memMgr); for (int i = 0; i < count; i++) { long key = newKey(); long value = newValue(); entries.put(key, value); } map.putAll(entries); assertEquals(count, map.size()); for (LongLongCursor cursor = map.cursor(); cursor.advance(); ) { assertEquals(map.get(cursor.key()), cursor.value()); } } @Test public void testReplace() throws Exception { long key = newKey(); long value = newValue(); assertEqualsKV(MISSING_VALUE, map.replace(key, value), key, value); map.put(key, value); long newValue = newValue(); assertEqualsKV(value, map.replace(key, newValue), key, value); } @Test public void testReplace_if_same_success() { long key = newKey(); long value = newValue(); map.put(key, value); long newValue = value + 1; assertTrueKV(map.replace(key, value, newValue), key, value); } @Test public void testReplace_if_same_not_exist() { long key = newKey(); long value = newValue(); long newValue = value + 1; assertFalseKV(map.replace(key, value, newValue), key, value); } @Test public void testReplace_if_same_fail() { long key = newKey(); long value = newValue(); map.put(key, value); long wrongValue = value + 1; long newValue = value + 2; assertFalseKV(map.replace(key, wrongValue, newValue), key, newValue); } @Test public void testRemove() { long key = newKey(); assertEqualsKV(MISSING_VALUE, map.remove(key), key, 0); long value = newValue(); map.put(key, value); long oldValue = map.remove(key); assertEqualsKV(value, oldValue, key, value); } @Test public void testRemove_if_same_success() { long key = newKey(); long value = newValue(); map.put(key, value); assertTrueKV(map.remove(key, value), key, value); } @Test public void testRemove_if_same_not_exist() { long key = newKey(); long value = newValue(); assertFalseKV(map.remove(key, value), key, value); } @Test public void testRemove_if_same_fail() { long key = newKey(); long value = newValue(); map.put(key, value); long wrongValue = value + 1; assertFalseKV(map.remove(key, wrongValue), key, value); } @Test public void testContainsKey_fail() throws Exception { long key = newKey(); assertFalseKV(map.containsKey(key), key, 0); } @Test public void testContainsKey_success() { long key = newKey(); long value = newValue(); map.put(key, value); assertTrueKV(map.containsKey(key), key, value); } @Test public void testPut_withTheSameValue() { long key = newKey(); long value = newValue(); map.put(key, value); long oldValue = map.put(key, value); assertEqualsKV(value, oldValue, key, value); } @Test(expected = AssertionError.class) @RequireAssertEnabled public void test_put_invalidValue() { map.put(newKey(), MISSING_VALUE); } @Test(expected = AssertionError.class) @RequireAssertEnabled public void test_putIfAbsent_invalidValue() { map.putIfAbsent(newKey(), MISSING_VALUE); } @Test(expected = AssertionError.class) @RequireAssertEnabled public void test_set_invalidValue() { map.put(newKey(), MISSING_VALUE); } @Test(expected = AssertionError.class) @RequireAssertEnabled public void test_replace_invalidValue() { map.replace(newKey(), MISSING_VALUE); } @Test(expected = AssertionError.class) @RequireAssertEnabled public void test_replaceIfEquals_invalidOldValue() { map.replace(newKey(), MISSING_VALUE, newValue()); } @Test(expected = AssertionError.class) @RequireAssertEnabled public void test_replaceIfEquals_invalidNewValue() { map.replace(newKey(), newValue(), MISSING_VALUE); } @Test(expected = AssertionError.class) @RequireAssertEnabled public void test_removeIfEquals_Value() { map.remove(newKey(), MISSING_VALUE); } @Test public void testSize() { assertEquals(0, map.size()); int expected = 100; for (long i = 0; i < expected; i++) { long value = newValue(); map.put(i, value); } assertEquals(map.toString(), expected, map.size()); } @Test public void testClear() { for (long i = 0; i < 100; i++) { long value = newValue(); map.put(i, value); } map.clear(); assertEquals(0, map.size()); assertTrue(map.toString(), map.isEmpty()); } @Test public void testIsEmpty() { assertTrue(map.isEmpty()); long key = newKey(); long value = newValue(); map.put(key, value); assertFalseKV(map.isEmpty(), key, value); } @Test(expected = AssertionError.class) @RequireAssertEnabled public void testGet_after_dispose() { map.dispose(); map.get(newKey()); } @Test(expected = AssertionError.class) @RequireAssertEnabled public void testPut_after_dispose() { map.dispose(); map.put(newKey(), newValue()); } @Test(expected = AssertionError.class) @RequireAssertEnabled public void testRemove_after_dispose() { map.dispose(); map.remove(newKey()); } @Test(expected = AssertionError.class) @RequireAssertEnabled public void testReplace_after_dispose() { map.dispose(); map.replace(newKey(), newValue()); } @Test(expected = AssertionError.class) @RequireAssertEnabled public void testContainsKey_after_dispose() { map.dispose(); map.containsKey(newKey()); } @Test public void testMemoryLeak() { int keyRange = 100; for (int i = 0; i < 100000; i++) { int k = random.nextInt(7); switch (k) { case 0: _put_(keyRange); break; case 1: _set_(keyRange); break; case 2: _putIfAbsent_(keyRange); break; case 3: _replace_(keyRange); break; case 4: _replaceIfSame_(keyRange); break; case 5: _remove_(keyRange); break; case 6: _removeIfPresent_(keyRange); break; } } map.clear(); map.dispose(); assertEquals(0, memMgr.getUsedMemory()); } private void _put_(int keyRange) { map.put(newKey(keyRange), newValue()); } private void _set_(int keyRange) { map.put(newKey(keyRange), newValue()); } private void _putIfAbsent_(int keyRange) { map.putIfAbsent(newKey(keyRange), newValue()); } private void _replace_(int keyRange) { map.replace(newKey(keyRange), newValue()); } private void _replaceIfSame_(int keyRange) { long key = newKey(keyRange); long value = newValue(); long old = map.get(key); if (old != MISSING_VALUE) { map.replace(key, old, value); } } private void _remove_(int keyRange) { map.remove(newKey(keyRange)); } private void _removeIfPresent_(int keyRange) { long key = newKey(keyRange); long old = map.get(key); if (old != MISSING_VALUE) { map.remove(key, old); } } @Test public void testDestroyMemoryLeak() { for (int i = 0; i < 100; i++) { map.put(newKey(), newValue()); } map.clear(); map.dispose(); assertEquals(0, memMgr.getUsedMemory()); } @Test public void testMemoryLeak_whenCapacityExpandFails() { while (true) { long key = newKey(); long value = newValue(); try { map.put(key, value); } catch (OutOfMemoryError e) { break; } } map.clear(); map.dispose(); assertEquals(0, memMgr.getUsedMemory()); } private long newKey() { return random.nextLong(); } private long newKey(int keyRange) { return (long) random.nextInt(keyRange); } private long newValue() { return random.nextInt(Integer.MAX_VALUE) + 1L; } private static void assertEqualsKV(long expected, long actual, long key, long value) { Assert.assertEquals(String.format("key %d value %d", key, value), expected, actual); } private static void assertTrueKV(boolean actual, long key, long value) { Assert.assertTrue(String.format("key %d value %d", key, value), actual); } private static void assertFalseKV(boolean actual, long key, long value) { Assert.assertFalse(String.format("key %d value %d", key, value), actual); } }