/*
* 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.map;
import com.hazelcast.config.Config;
import com.hazelcast.core.EntryAdapter;
import com.hazelcast.core.EntryEvent;
import com.hazelcast.core.EntryListener;
import com.hazelcast.core.EntryView;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.IMap;
import com.hazelcast.core.MapEvent;
import com.hazelcast.query.Predicate;
import com.hazelcast.test.AssertTask;
import com.hazelcast.test.HazelcastParallelClassRunner;
import com.hazelcast.test.HazelcastTestSupport;
import com.hazelcast.test.TestHazelcastInstanceFactory;
import com.hazelcast.test.annotation.ParallelTest;
import com.hazelcast.test.annotation.QuickTest;
import com.hazelcast.util.Clock;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import java.io.Serializable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@RunWith(HazelcastParallelClassRunner.class)
@Category({QuickTest.class, ParallelTest.class})
public class BasicMapTest extends HazelcastTestSupport {
static final int INSTANCE_COUNT = 3;
static final Random RANDOM = new Random();
HazelcastInstance[] instances;
@Before
public void init() {
TestHazelcastInstanceFactory factory = createHazelcastInstanceFactory(INSTANCE_COUNT);
Config config = getConfig();
instances = factory.newInstances(config);
}
HazelcastInstance getInstance() {
return instances[RANDOM.nextInt(INSTANCE_COUNT)];
}
@Test
@SuppressWarnings({"UnnecessaryBoxing", "BooleanConstructorCall"})
public void testBoxedPrimitives() {
IMap<String, Object> map = getInstance().getMap("testPrimitives");
assertPutGet(map, new Boolean(true));
assertPutGet(map, new Boolean(false));
assertPutGet(map, new Integer(10));
assertPutGet(map, new Short((short) 10));
assertPutGet(map, new Byte((byte) 10));
assertPutGet(map, new Long(10));
assertPutGet(map, new Float(10));
assertPutGet(map, new Double(10));
assertPutGet(map, new Character('x'));
}
public void assertPutGet(Map<String, Object> map, Object value) {
String key = UUID.randomUUID().toString();
map.put(key, value);
assertEquals(value, map.get(key));
}
@Test
public void testArrays() {
IMap<String, Object> map = getInstance().getMap("testArrays");
boolean[] booleanArray = {true, false};
map.put("boolean", booleanArray);
assertTrue(Arrays.equals(booleanArray, (boolean[]) map.get("boolean")));
int[] intArray = {1, 2};
map.put("int", intArray);
assertArrayEquals(intArray, (int[]) map.get("int"));
short[] shortArray = {(short) 1, (short) 2};
map.put("short", shortArray);
assertArrayEquals(shortArray, (short[]) map.get("short"));
short[] byteArray = {(byte) 1, (byte) 2};
map.put("byte", byteArray);
assertArrayEquals(byteArray, (short[]) map.get("byte"));
long[] longArray = {1L, 2L};
map.put("long", longArray);
assertArrayEquals(longArray, (long[]) map.get("long"));
float[] floatArray = {(float) 1, (float) 2};
map.put("float", floatArray);
assertTrue(Arrays.equals(floatArray, (float[]) map.get("float")));
double[] doubleArray = {(double) 1, (double) 2};
map.put("double", doubleArray);
assertTrue(Arrays.equals(doubleArray, (double[]) map.get("double")));
char[] charArray = {'1', '2'};
map.put("char", charArray);
assertArrayEquals(charArray, (char[]) map.get("char"));
Object[] objectArray = {"foo", null, Integer.decode("3")};
map.put("object", objectArray);
assertArrayEquals(objectArray, (Object[]) map.get("object"));
}
@Test
public void testMapPutAndGet() {
IMap<String, String> map = getInstance().getMap("testMapPutAndGet");
String value = map.put("Hello", "World");
assertEquals("World", map.get("Hello"));
assertEquals(1, map.size());
assertNull(value);
value = map.put("Hello", "World");
assertEquals("World", map.get("Hello"));
assertEquals(1, map.size());
assertEquals("World", value);
value = map.put("Hello", "New World");
assertEquals("World", value);
assertEquals("New World", map.get("Hello"));
}
@Test
public void testMapPutIfAbsent() {
IMap<String, String> map = getInstance().getMap("testMapPutIfAbsent");
assertEquals(map.putIfAbsent("key1", "value1"), null);
assertEquals(map.putIfAbsent("key2", "value2"), null);
assertEquals(map.putIfAbsent("key1", "valueX"), "value1");
assertEquals(map.get("key1"), "value1");
assertEquals(map.size(), 2);
}
@Test
public void testMapGetNullIsNotAllowed() {
IMap<String, String> map = getInstance().getMap("testMapGetNullIsNotAllowed");
try {
map.get(null);
fail();
} catch (Exception e) {
assertTrue(e instanceof NullPointerException);
}
}
@Test
public void testMapEvictAndListener() {
IMap<String, String> map = getInstance().getMap("testMapEvictAndListener");
final String value1 = "/home/data/file1.dat";
final String value2 = "/home/data/file2.dat";
final AtomicReference<String> oldValue1 = new AtomicReference<String>();
final AtomicReference<String> oldValue2 = new AtomicReference<String>();
final CountDownLatch latch1 = new CountDownLatch(1);
final CountDownLatch latch2 = new CountDownLatch(1);
map.addEntryListener(new EntryAdapter<String, String>() {
@Override
public void entryEvicted(EntryEvent<String, String> event) {
if (value1.equals(event.getOldValue())) {
oldValue1.set(event.getOldValue());
latch1.countDown();
} else if (value2.equals(event.getOldValue())) {
oldValue2.set(event.getOldValue());
latch2.countDown();
}
}
}, true);
map.put("key", value1, 1, SECONDS);
assertOpenEventually(latch1);
map.put("key", value2, 1, SECONDS);
assertOpenEventually(latch2);
assertEquals(value1, oldValue1.get());
assertEquals(value2, oldValue2.get());
}
@Test
public void testMapEntryListener() {
IMap<String, String> map = getInstance().getMap("testMapEntryListener");
final CountDownLatch latchAdded = new CountDownLatch(1);
final CountDownLatch latchRemoved = new CountDownLatch(1);
final CountDownLatch latchUpdated = new CountDownLatch(1);
final CountDownLatch latchCleared = new CountDownLatch(1);
final CountDownLatch latchEvicted = new CountDownLatch(1);
map.addEntryListener(new EntryListener<String, String>() {
@Override
public void entryAdded(EntryEvent event) {
latchAdded.countDown();
}
@Override
public void entryRemoved(EntryEvent event) {
assertEquals("hello", event.getKey());
assertEquals("new world", event.getOldValue());
latchRemoved.countDown();
}
@Override
public void entryUpdated(EntryEvent event) {
assertEquals("world", event.getOldValue());
assertEquals("new world", event.getValue());
assertEquals("hello", event.getKey());
latchUpdated.countDown();
}
@Override
public void entryEvicted(EntryEvent event) {
entryRemoved(event);
}
@Override
public void mapEvicted(MapEvent event) {
latchEvicted.countDown();
}
@Override
public void mapCleared(MapEvent event) {
latchCleared.countDown();
}
}, true);
map.put("hello", "world");
map.put("hello", "new world");
map.remove("hello");
map.put("hi", "new world");
map.evictAll();
map.put("hello", "world");
map.clear();
try {
assertTrue(latchAdded.await(5, SECONDS));
assertTrue(latchUpdated.await(5, SECONDS));
assertTrue(latchRemoved.await(5, SECONDS));
assertTrue(latchEvicted.await(5, SECONDS));
assertTrue(latchCleared.await(5, SECONDS));
} catch (InterruptedException e) {
e.printStackTrace();
assertFalse(e.getMessage(), true);
}
}
/**
* Test for issue #181
*/
@Test
public void testMapKeyListenerWithRemoveAndUnlock() throws Exception {
int count = 20;
IMap<String, String> map = getInstance().getMap("testMapKeyListenerWithRemoveAndUnlock");
final String key = "key";
final CountDownLatch latch = new CountDownLatch(count * 2);
map.addEntryListener(new EntryAdapter<String, String>() {
@Override
public void entryAdded(EntryEvent<String, String> e) {
testEvent(e);
}
@Override
public void entryRemoved(EntryEvent<String, String> e) {
testEvent(e);
}
private void testEvent(EntryEvent<String, String> e) {
if (key.equals(e.getKey())) {
latch.countDown();
} else {
fail("Invalid event: " + e);
}
}
}, key, true);
for (int i = 0; i < count; i++) {
map.lock(key);
map.put(key, "value");
map.remove(key);
map.unlock(key);
}
assertTrue("Listener events are missing! Remaining: " + latch.getCount(), latch.await(5, SECONDS));
}
@Test
public void testMapRemove() {
IMap<String, String> map = getInstance().getMap("testMapRemove");
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
assertEquals(map.remove("key1"), "value1");
assertEquals(map.size(), 2);
assertEquals(map.remove("key1"), null);
assertEquals(map.size(), 2);
assertEquals(map.remove("key3"), "value3");
assertEquals(map.size(), 1);
}
@Test
public void testMapDelete() {
IMap<String, String> map = getInstance().getMap("testMapRemove");
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
map.delete("key1");
assertEquals(map.size(), 2);
map.delete("key1");
assertEquals(map.size(), 2);
map.delete("key3");
assertEquals(map.size(), 1);
}
@Test
public void testMapClear_nonEmptyMap() {
IMap<String, String> map = getInstance().getMap("testMapClear");
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
map.clear();
assertEquals(map.size(), 0);
assertEquals(map.get("key1"), null);
assertEquals(map.get("key2"), null);
assertEquals(map.get("key3"), null);
}
@Test
public void testMapClear_emptyMap() {
String mapName = "testMapClear_emptyMap";
HazelcastInstance hz = getInstance();
IMap<String, String> map = hz.getMap(mapName);
map.clear();
assertEquals(map.size(), 0);
// TODO: This test is going to be enabled as soon as the size has been fixed (since it also triggers unwanted RecordStore
// creation). We need to make sure there are no unwanted RecordStores (consumes memory) being created because of the
// clear. So we are going to check one of the partitions if it has a RecordStore and then we can safely assume that the
// rest of the partitions have no record store either.
// MapService mapService = getNode(hz).nodeEngine.getService(MapService.SERVICE_NAME);
// RecordStore recordStore = mapService.getPartitionContainer(1).getExistingRecordStore(mapName);
// assertNull(recordStore);
}
@Test
public void testMapEvict() {
IMap<String, String> map = getInstance().getMap("testMapEvict");
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
assertEquals(map.remove("key1"), "value1");
assertEquals(map.size(), 2);
assertEquals(map.remove("key1"), null);
assertEquals(map.size(), 2);
assertEquals(map.remove("key3"), "value3");
assertEquals(map.size(), 1);
}
@Test
public void testMapEvictAll() {
IMap<String, String> map = getInstance().getMap("testMapEvict");
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
map.evictAll();
assertEquals(0, map.size());
}
@Test
public void testMapTryRemove() throws Exception {
final IMap<Object, Object> map = getInstance().getMap("testMapTryRemove");
map.put("key1", "value1");
map.lock("key1");
final CountDownLatch latch1 = new CountDownLatch(1);
final CountDownLatch latch2 = new CountDownLatch(1);
final CountDownLatch latch3 = new CountDownLatch(1);
final AtomicBoolean firstBool = new AtomicBoolean();
final AtomicBoolean secondBool = new AtomicBoolean();
Thread thread = new Thread(new Runnable() {
public void run() {
try {
firstBool.set(map.tryRemove("key1", 1, SECONDS));
latch2.countDown();
latch1.await();
secondBool.set(map.tryRemove("key1", 1, SECONDS));
latch3.countDown();
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
}
}
});
thread.start();
latch2.await();
map.unlock("key1");
latch1.countDown();
latch3.await();
assertFalse(firstBool.get());
assertTrue(secondBool.get());
thread.join();
}
@Test
public void testMapRemoveIfSame() {
IMap<String, String> map = getInstance().getMap("testMapRemoveIfSame");
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
assertFalse(map.remove("key1", "nan"));
assertEquals(map.size(), 3);
assertTrue(map.remove("key1", "value1"));
assertEquals(map.size(), 2);
assertTrue(map.remove("key2", "value2"));
assertTrue(map.remove("key3", "value3"));
assertEquals(map.size(), 0);
}
@Test
public void testMapSet() {
IMap<String, String> map = getInstance().getMap("testMapSet");
map.put("key1", "value1");
assertEquals(map.get("key1"), "value1");
assertEquals(map.size(), 1);
map.set("key1", "valueX", 0, TimeUnit.MILLISECONDS);
assertEquals(map.size(), 1);
assertEquals(map.get("key1"), "valueX");
map.set("key2", "value2", 0, TimeUnit.MILLISECONDS);
assertEquals(map.size(), 2);
assertEquals(map.get("key1"), "valueX");
assertEquals(map.get("key2"), "value2");
}
@Test
public void testMapContainsKey() {
IMap<String, String> map = getInstance().getMap("testMapContainsKey");
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
assertEquals(map.containsKey("key1"), true);
assertEquals(map.containsKey("key5"), false);
map.remove("key1");
assertEquals(map.containsKey("key1"), false);
assertEquals(map.containsKey("key2"), true);
assertEquals(map.containsKey("key5"), false);
}
@Test
public void testMapContainsValue() {
IMap<Integer, Integer> map = getInstance().getMap("testMapContainsValue");
map.put(1, 1);
map.put(2, 2);
map.put(3, 3);
assertTrue(map.containsValue(1));
assertFalse(map.containsValue(5));
map.remove(1);
assertFalse(map.containsValue(1));
assertTrue(map.containsValue(2));
assertFalse(map.containsValue(5));
}
@Test
public void testMapIsEmpty() {
IMap<String, String> map = getInstance().getMap("testMapIsEmpty");
assertTrue(map.isEmpty());
map.put("key1", "value1");
assertFalse(map.isEmpty());
map.remove("key1");
assertTrue(map.isEmpty());
}
@Test
public void testMapSize() {
IMap<Integer, Integer> map = getInstance().getMap("testMapSize");
assertEquals(map.size(), 0);
map.put(1, 1);
assertEquals(map.size(), 1);
map.put(2, 2);
map.put(3, 3);
assertEquals(map.size(), 3);
}
@Test
public void testMapReplace() {
IMap<Integer, Integer> map = getInstance().getMap("testMapReplace");
map.put(1, 1);
assertNull(map.replace(2, 1));
assertNull(map.get(2));
map.put(2, 2);
assertEquals(2, map.replace(2, 3).intValue());
assertEquals(3, map.get(2).intValue());
}
@Test
public void testMapReplaceIfSame() {
IMap<Integer, Integer> map = getInstance().getMap("testMapReplaceIfSame");
map.put(1, 1);
assertFalse(map.replace(1, 2, 3));
assertTrue(map.replace(1, 1, 2));
assertEquals(map.get(1).intValue(), 2);
map.put(2, 2);
assertTrue(map.replace(2, 2, 3));
assertEquals(map.get(2).intValue(), 3);
assertTrue(map.replace(2, 3, 4));
assertEquals(map.get(2).intValue(), 4);
}
@Test
public void testMapLockAndUnlockAndTryLock() throws Exception {
final int timeout = 10; //seconds
final IMap<Object, Object> map = getInstance().getMap("testMapLockAndUnlockAndTryLock");
map.lock("key0");
map.lock("key1");
map.lock("key2");
map.lock("key3");
final AtomicBoolean check1 = new AtomicBoolean(false);
final AtomicBoolean check2 = new AtomicBoolean(false);
final CountDownLatch latch0 = new CountDownLatch(1);
final CountDownLatch latch1 = new CountDownLatch(1);
final CountDownLatch latch2 = new CountDownLatch(1);
final CountDownLatch latch3 = new CountDownLatch(1);
final CountDownLatch latch4 = new CountDownLatch(1);
Thread thread = new Thread(new Runnable() {
public void run() {
try {
check1.set(map.tryLock("key0"));
latch0.countDown();
check2.set(map.tryLock("key0", timeout, SECONDS));
latch1.countDown();
map.put("key1", "value1");
latch2.countDown();
map.put("key2", "value2");
latch3.countDown();
map.put("key3", "value3");
latch4.countDown();
} catch (Exception e) {
fail(e.getMessage());
}
}
});
thread.start();
assertTrue(latch0.await(timeout, SECONDS));
map.unlock("key0");
assertTrue(latch1.await(timeout, SECONDS));
assertFalse(check1.get());
assertTrue(check2.get());
map.unlock("key1");
assertTrue(latch2.await(timeout, SECONDS));
map.unlock("key2");
assertTrue(latch3.await(timeout, SECONDS));
map.unlock("key3");
assertTrue(latch4.await(timeout, SECONDS));
}
@Test
public void testMapIsLocked() throws Exception {
final IMap<Object, Object> map = getInstance().getMap("testMapIsLocked");
map.lock("key1");
assertTrue(map.isLocked("key1"));
assertFalse(map.isLocked("key2"));
final CountDownLatch latch = new CountDownLatch(1);
final AtomicBoolean b1 = new AtomicBoolean();
final AtomicBoolean b2 = new AtomicBoolean();
Thread thread = new Thread(new Runnable() {
public void run() {
try {
b1.set(map.isLocked("key1"));
b2.set(map.isLocked("key2"));
latch.countDown();
} catch (Exception e) {
fail(e.getMessage());
}
}
});
thread.start();
latch.await();
assertTrue(b1.get());
assertFalse(b2.get());
thread.join();
}
@Test
public void testEntryView() {
Config config = new Config();
config.getMapConfig("default").setStatisticsEnabled(true);
HazelcastInstance instance = getInstance();
IMap<Integer, Integer> map = instance.getMap("testEntryView");
long time1 = Clock.currentTimeMillis();
map.put(1, 1);
map.put(1, 1);
map.get(1);
map.put(2, 2);
map.put(2, 2);
map.get(2);
map.put(3, 3);
map.put(3, 3);
long time2 = Clock.currentTimeMillis();
map.get(3);
map.get(3);
long time3 = Clock.currentTimeMillis();
map.put(2, 22);
EntryView<Integer, Integer> entryView1 = map.getEntryView(1);
EntryView<Integer, Integer> entryView2 = map.getEntryView(2);
EntryView<Integer, Integer> entryView3 = map.getEntryView(3);
assertEquals((Integer) 1, entryView1.getKey());
assertEquals((Integer) 2, entryView2.getKey());
assertEquals((Integer) 3, entryView3.getKey());
assertEquals((Integer) 1, entryView1.getValue());
assertEquals((Integer) 22, entryView2.getValue());
assertEquals((Integer) 3, entryView3.getValue());
assertEquals(2, entryView1.getHits());
assertEquals(3, entryView2.getHits());
assertEquals(3, entryView3.getHits());
assertEquals(1, entryView1.getVersion());
assertEquals(2, entryView2.getVersion());
assertEquals(1, entryView3.getVersion());
assertTrue(entryView1.getCreationTime() >= time1 && entryView1.getCreationTime() <= time2);
assertTrue(entryView2.getCreationTime() >= time1 && entryView2.getCreationTime() <= time2);
assertTrue(entryView3.getCreationTime() >= time1 && entryView3.getCreationTime() <= time2);
assertTrue(entryView1.getLastAccessTime() >= time1 && entryView1.getLastAccessTime() <= time2);
assertTrue(entryView2.getLastAccessTime() >= time3);
assertTrue(entryView3.getLastAccessTime() >= time2 && entryView3.getLastAccessTime() <= time3);
assertTrue(entryView1.getLastUpdateTime() >= time1 && entryView1.getLastUpdateTime() <= time2);
assertTrue(entryView2.getLastUpdateTime() >= time3);
assertTrue(entryView3.getLastUpdateTime() >= time1 && entryView3.getLastUpdateTime() <= time2);
}
@Test
public void testTryPut_whenKeyNotLocked() {
IMap<Object, Object> map = getInstance().getMap(randomMapName());
String key = "key";
String value = "value";
assertTrue(map.tryPut(key, value, 1, SECONDS));
assertEquals(value, map.get(key));
}
@Test
public void testTryPut_fails_whenKeyLocked() throws Exception {
final IMap<Object, Object> map = getInstance().getMap(randomMapName());
final String key = "key";
final String value = "value";
// lock the key
spawn(new Callable<Object>() {
@Override
public Object call() throws Exception {
map.lock(key);
return null;
}
}).get(30, SECONDS);
assertFalse(map.tryPut(key, value, 100, TimeUnit.MILLISECONDS));
}
@Test
public void testTryPut_whenKeyLocked_thenUnlocked() throws Exception {
final IMap<Object, Object> map = getInstance().getMap(randomMapName());
final String key = "key";
final String value = "value";
map.lock(key);
final CountDownLatch tryPutFailureLatch = new CountDownLatch(1);
Future<Object> future = spawn(new Callable<Object>() {
@Override
public Object call() throws Exception {
try {
assertFalse("tryPut() on a locked key should fail!",
map.tryPut(key, value, 100, TimeUnit.MILLISECONDS));
} finally {
tryPutFailureLatch.countDown();
}
assertTrue("tryPut() should have been succeeded, key is already unlocked!",
map.tryPut(key, value, 30, SECONDS));
return null;
}
});
tryPutFailureLatch.await(30, SECONDS);
map.unlock(key);
future.get(ASSERT_TRUE_EVENTUALLY_TIMEOUT, SECONDS);
assertEquals(value, map.get(key));
}
@Test
public void testGetPutRemoveAsync() {
IMap<Integer, Object> map = getInstance().getMap("testGetPutRemoveAsync");
Future<Object> future = map.putAsync(1, 1);
try {
assertNull(future.get());
assertEquals(1, map.putAsync(1, 2).get());
assertEquals(2, map.getAsync(1).get());
assertEquals(2, map.removeAsync(1).get());
assertEquals(0, map.size());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
@Test
public void testGetAllPutAll() {
warmUpPartitions(instances);
IMap<Integer, Integer> map = getInstance().getMap("testGetAllPutAll");
Set<Integer> set = new HashSet<Integer>();
set.add(1);
set.add(3);
map.getAll(set);
assertTrue(map.isEmpty());
int size = 100;
Map<Integer, Integer> mm = new HashMap<Integer, Integer>();
for (int i = 0; i < size; i++) {
mm.put(i, i);
}
map.putAll(mm);
assertEquals(size, map.size());
for (int i = 0; i < size; i++) {
assertEquals(map.get(i).intValue(), i);
}
size = 10000;
for (int i = 0; i < size; i++) {
mm.put(i, i);
}
map.putAll(mm);
assertEquals(size, map.size());
for (int i = 0; i < size; i++) {
assertEquals(map.get(i).intValue(), i);
}
set = new HashSet<Integer>();
set.add(1);
set.add(3);
Map m2 = map.getAll(set);
assertEquals(m2.size(), 2);
assertEquals(m2.get(1), 1);
assertEquals(m2.get(3), 3);
}
@Test
public void testPutAllBackup() {
int size = 100;
HazelcastInstance instance1 = instances[0];
HazelcastInstance instance2 = instances[1];
IMap<Integer, Integer> map1 = instance1.getMap("testPutAllBackup");
IMap<Integer, Integer> map2 = instance2.getMap("testPutAllBackup");
warmUpPartitions(instances);
Map<Integer, Integer> mm = new HashMap<Integer, Integer>();
for (int i = 0; i < size; i++) {
mm.put(i, i);
}
map2.putAll(mm);
assertEquals(size, map2.size());
for (int i = 0; i < size; i++) {
assertEquals(i, map2.get(i).intValue());
}
instance2.shutdown();
assertEquals(size, map1.size());
for (int i = 0; i < size; i++) {
assertEquals(i, map1.get(i).intValue());
}
}
@Test
public void testPutAllTooManyEntriesWithBackup() {
int size = 10000;
HazelcastInstance instance1 = instances[0];
HazelcastInstance instance2 = instances[1];
IMap<Integer, Integer> map1 = instance1.getMap("testPutAllTooManyEntries");
IMap<Integer, Integer> map2 = instance2.getMap("testPutAllTooManyEntries");
warmUpPartitions(instances);
Map<Integer, Integer> mm = new HashMap<Integer, Integer>();
for (int i = 0; i < size; i++) {
mm.put(i, i);
}
map2.putAll(mm);
assertEquals(size, map2.size());
for (int i = 0; i < size; i++) {
assertEquals(i, map2.get(i).intValue());
}
instance2.shutdown();
assertEquals(size, map1.size());
for (int i = 0; i < size; i++) {
assertEquals(i, map1.get(i).intValue());
}
}
@Test
public void testMapListenersWithValue() {
IMap<Object, Object> map = getInstance().getMap("testMapListenersWithValue");
final Object[] addedKey = new Object[1];
final Object[] addedValue = new Object[1];
final Object[] updatedKey = new Object[1];
final Object[] oldValue = new Object[1];
final Object[] newValue = new Object[1];
final Object[] removedKey = new Object[1];
final Object[] removedValue = new Object[1];
EntryListener<Object, Object> listener = new EntryAdapter<Object, Object>() {
@Override
public void entryAdded(EntryEvent<Object, Object> event) {
addedKey[0] = event.getKey();
addedValue[0] = event.getValue();
}
@Override
public void entryRemoved(EntryEvent<Object, Object> event) {
removedKey[0] = event.getKey();
removedValue[0] = event.getOldValue();
}
@Override
public void entryUpdated(EntryEvent<Object, Object> event) {
updatedKey[0] = event.getKey();
oldValue[0] = event.getOldValue();
newValue[0] = event.getValue();
}
public void entryEvicted(EntryEvent<Object, Object> event) {
}
@Override
public void mapEvicted(MapEvent event) {
}
@Override
public void mapCleared(MapEvent event) {
}
};
map.addEntryListener(listener, true);
map.put("key", "value");
map.put("key", "value2");
map.remove("key");
sleepSeconds(1);
assertEquals(addedKey[0], "key");
assertEquals(addedValue[0], "value");
assertEquals(updatedKey[0], "key");
assertEquals(oldValue[0], "value");
assertEquals(newValue[0], "value2");
assertEquals(removedKey[0], "key");
assertEquals(removedValue[0], "value2");
}
@Test
public void testMapQueryListener() {
IMap<Object, Object> map = getInstance().getMap(randomMapName());
final Object[] addedKey = new Object[1];
final Object[] addedValue = new Object[1];
final Object[] updatedKey = new Object[1];
final Object[] oldValue = new Object[1];
final Object[] newValue = new Object[1];
final Object[] removedKey = new Object[1];
final Object[] removedValue = new Object[1];
EntryListener<Object, Object> listener = new EntryAdapter<Object, Object>() {
@Override
public void entryAdded(EntryEvent<Object, Object> event) {
addedKey[0] = event.getKey();
addedValue[0] = event.getValue();
}
@Override
public void entryRemoved(EntryEvent<Object, Object> event) {
removedKey[0] = event.getKey();
removedValue[0] = event.getOldValue();
}
@Override
public void entryUpdated(EntryEvent<Object, Object> event) {
updatedKey[0] = event.getKey();
oldValue[0] = event.getOldValue();
newValue[0] = event.getValue();
}
@Override
public void entryEvicted(EntryEvent<Object, Object> event) {
}
@Override
public void mapEvicted(MapEvent event) {
}
@Override
public void mapCleared(MapEvent event) {
}
};
map.addEntryListener(listener, new StartsWithPredicate("a"), null, true);
map.put("key1", "abc");
map.put("key2", "bcd");
map.put("key2", "axyz");
map.remove("key1");
assertTrueEventually(new AssertTask() {
@Override
public void run() {
assertEquals("key1", addedKey[0]);
assertEquals("abc", addedValue[0]);
assertEquals("key2", updatedKey[0]);
assertEquals("bcd", oldValue[0]);
assertEquals("axyz", newValue[0]);
assertEquals("key1", removedKey[0]);
assertEquals("abc", removedValue[0]);
}
});
}
private static class StartsWithPredicate implements Predicate<Object, Object>, Serializable {
private static final long serialVersionUID = 4193947125511602220L;
String pref;
StartsWithPredicate(String pref) {
this.pref = pref;
}
@Override
public boolean apply(Map.Entry<Object, Object> mapEntry) {
String val = (String) mapEntry.getValue();
if (val == null) {
return false;
}
if (val.startsWith(pref)) {
return true;
}
return false;
}
}
@Test
public void testMapListenersWithValueAndKeyFiltered() {
IMap<Object, Object> map = getInstance().getMap("testMapListenersWithValueAndKeyFiltered");
final Object[] addedKey = new Object[1];
final Object[] addedValue = new Object[1];
final Object[] updatedKey = new Object[1];
final Object[] oldValue = new Object[1];
final Object[] newValue = new Object[1];
final Object[] removedKey = new Object[1];
final Object[] removedValue = new Object[1];
EntryListener<Object, Object> listener = new EntryAdapter<Object, Object>() {
@Override
public void entryAdded(EntryEvent<Object, Object> event) {
addedKey[0] = event.getKey();
addedValue[0] = event.getValue();
}
@Override
public void entryRemoved(EntryEvent<Object, Object> event) {
removedKey[0] = event.getKey();
removedValue[0] = event.getOldValue();
}
@Override
public void entryUpdated(EntryEvent<Object, Object> event) {
updatedKey[0] = event.getKey();
oldValue[0] = event.getOldValue();
newValue[0] = event.getValue();
}
@Override
public void entryEvicted(EntryEvent<Object, Object> event) {
}
@Override
public void mapEvicted(MapEvent event) {
}
@Override
public void mapCleared(MapEvent event) {
}
};
map.addEntryListener(listener, "key", true);
map.put("keyx", "valuex");
map.put("key", "value");
map.put("key", "value2");
map.put("keyx", "valuex2");
map.put("keyz", "valuez");
map.remove("keyx");
map.remove("key");
map.remove("keyz");
sleepSeconds(1);
assertEquals(addedKey[0], "key");
assertEquals(addedValue[0], "value");
assertEquals(updatedKey[0], "key");
assertEquals(oldValue[0], "value");
assertEquals(newValue[0], "value2");
assertEquals(removedKey[0], "key");
assertEquals(removedValue[0], "value2");
}
@Test
public void testMapListenersWithoutValue() {
IMap<Object, Object> map = getInstance().getMap("testMapListenersWithoutValue");
final Object[] addedKey = new Object[1];
final Object[] addedValue = new Object[1];
final Object[] updatedKey = new Object[1];
final Object[] oldValue = new Object[1];
final Object[] newValue = new Object[1];
final Object[] removedKey = new Object[1];
final Object[] removedValue = new Object[1];
EntryListener<Object, Object> listener = new EntryAdapter<Object, Object>() {
@Override
public void entryAdded(EntryEvent<Object, Object> event) {
addedKey[0] = event.getKey();
addedValue[0] = event.getValue();
}
@Override
public void entryRemoved(EntryEvent<Object, Object> event) {
removedKey[0] = event.getKey();
removedValue[0] = event.getOldValue();
}
@Override
public void entryUpdated(EntryEvent<Object, Object> event) {
updatedKey[0] = event.getKey();
oldValue[0] = event.getOldValue();
newValue[0] = event.getValue();
}
@Override
public void entryEvicted(EntryEvent<Object, Object> event) {
}
@Override
public void mapEvicted(MapEvent event) {
}
@Override
public void mapCleared(MapEvent event) {
}
};
map.addEntryListener(listener, false);
map.put("key", "value");
map.put("key", "value2");
map.remove("key");
sleepSeconds(1);
assertEquals(addedKey[0], "key");
assertEquals(addedValue[0], null);
assertEquals(updatedKey[0], "key");
assertEquals(oldValue[0], null);
assertEquals(newValue[0], null);
assertEquals(removedKey[0], "key");
assertEquals(removedValue[0], null);
}
@Test
public void testPutWithTtl() {
final IMap<String, String> map = getInstance().getMap("testPutWithTtl");
map.put("key", "value", 2, SECONDS);
assertTrueEventually(new AssertTask() {
@Override
public void run() {
assertNull(map.get("key"));
}
}, 30);
}
@Test
public void testMapEntryProcessor() {
IMap<Integer, Integer> map = getInstance().getMap("testMapEntryProcessor");
map.put(1, 1);
EntryProcessor entryProcessor = new SampleEntryProcessor();
map.executeOnKey(1, entryProcessor);
assertEquals(map.get(1), (Object) 2);
}
@Test
public void testIfWeCarryRecordVersionInfoToReplicas() {
String mapName = randomMapName();
int mapSize = 1000;
int expectedRecordVersion = 3;
HazelcastInstance node1 = instances[1];
IMap<Integer, Integer> map1 = node1.getMap(mapName);
for (int i = 0; i < mapSize; i++) {
map1.put(i, 0); // version 0
map1.put(i, 1); // version 1
map1.put(i, 2); // version 2
map1.put(i, 3); // version 3
}
HazelcastInstance node2 = instances[2];
node1.shutdown();
IMap<Integer, Integer> map3 = node2.getMap(mapName);
for (int i = 0; i < mapSize; i++) {
EntryView<Integer, Integer> entryView = map3.getEntryView(i);
assertEquals(expectedRecordVersion, entryView.getVersion());
}
}
@Test
public void testNullChecks() {
final IMap<String, String> map = getInstance().getMap("testNullChecks");
Runnable runnable;
runnable = new Runnable() {
public void run() {
map.containsKey(null);
}
};
assertRunnableThrowsNullPointerException(runnable, "containsKey(null)");
runnable = new Runnable() {
public void run() {
map.containsValue(null);
}
};
assertRunnableThrowsNullPointerException(runnable, "containsValue(null)");
runnable = new Runnable() {
public void run() {
map.get(null);
}
};
assertRunnableThrowsNullPointerException(runnable, "get(null)");
runnable = new Runnable() {
public void run() {
map.put(null, "value");
}
};
assertRunnableThrowsNullPointerException(runnable, "put(null, \"value\")");
runnable = new Runnable() {
public void run() {
map.put("key", null);
}
};
assertRunnableThrowsNullPointerException(runnable, "put(\"key\", null)");
runnable = new Runnable() {
public void run() {
map.remove(null);
}
};
assertRunnableThrowsNullPointerException(runnable, "remove(null)");
runnable = new Runnable() {
public void run() {
map.remove(null, "value");
}
};
assertRunnableThrowsNullPointerException(runnable, "remove(null, \"value\")");
runnable = new Runnable() {
public void run() {
map.remove("key", null);
}
};
assertRunnableThrowsNullPointerException(runnable, "remove(\"key\", null)");
runnable = new Runnable() {
public void run() {
map.delete(null);
}
};
assertRunnableThrowsNullPointerException(runnable, "delete(null)");
final Set<String> keys = new HashSet<String>();
keys.add("key");
keys.add(null);
runnable = new Runnable() {
public void run() {
map.getAll(keys);
}
};
assertRunnableThrowsNullPointerException(runnable, "remove(keys)");
runnable = new Runnable() {
public void run() {
map.getAsync(null);
}
};
assertRunnableThrowsNullPointerException(runnable, "getAsync(null)");
runnable = new Runnable() {
public void run() {
map.putAsync(null, "value");
}
};
assertRunnableThrowsNullPointerException(runnable, "putAsync(null, \"value\")");
runnable = new Runnable() {
public void run() {
map.putAsync("key", null);
}
};
assertRunnableThrowsNullPointerException(runnable, "putAsync(\"key\", null)");
runnable = new Runnable() {
public void run() {
map.putAsync(null, "value", 1, SECONDS);
}
};
assertRunnableThrowsNullPointerException(runnable, "putAsync(null, \"value\", 1, TimeUnit.SECONDS)");
runnable = new Runnable() {
public void run() {
map.putAsync("key", null, 1, SECONDS);
}
};
assertRunnableThrowsNullPointerException(runnable, "putAsync(\"key\", null, 1, TimeUnit.SECONDS)");
runnable = new Runnable() {
public void run() {
map.removeAsync(null);
}
};
assertRunnableThrowsNullPointerException(runnable, "removeAsync(null)");
runnable = new Runnable() {
public void run() {
map.tryRemove(null, 1, SECONDS);
}
};
assertRunnableThrowsNullPointerException(runnable, "tryRemove(null, 1, TimeUnit.SECONDS)");
runnable = new Runnable() {
public void run() {
map.tryPut(null, "value", 1, SECONDS);
}
};
assertRunnableThrowsNullPointerException(runnable, "tryPut(null, \"value\", 1, TimeUnit.SECONDS)");
runnable = new Runnable() {
public void run() {
map.tryPut("key", null, 1, SECONDS);
}
};
assertRunnableThrowsNullPointerException(runnable, "tryPut(\"key\", null, 1, TimeUnit.SECONDS)");
runnable = new Runnable() {
public void run() {
map.putTransient(null, "value", 1, SECONDS);
}
};
assertRunnableThrowsNullPointerException(runnable, "putTransient(null, \"value\", 1, TimeUnit.SECONDS)");
runnable = new Runnable() {
public void run() {
map.putTransient("key", null, 1, SECONDS);
}
};
assertRunnableThrowsNullPointerException(runnable, "putTransient(\"key\", null, 1, TimeUnit.SECONDS)");
runnable = new Runnable() {
public void run() {
map.putIfAbsent(null, "value");
}
};
assertRunnableThrowsNullPointerException(runnable, "putIfAbsent(null, \"value\")");
runnable = new Runnable() {
public void run() {
map.putIfAbsent("key", null);
}
};
assertRunnableThrowsNullPointerException(runnable, "putIfAbsent(\"key\", null)");
runnable = new Runnable() {
public void run() {
map.putIfAbsent(null, "value", 1, SECONDS);
}
};
assertRunnableThrowsNullPointerException(runnable, "putIfAbsent(null, \"value\", 1, TimeUnit.SECONDS)");
runnable = new Runnable() {
public void run() {
map.putIfAbsent("key", null, 1, SECONDS);
}
};
assertRunnableThrowsNullPointerException(runnable, "putIfAbsent(\"key\", null, 1, TimeUnit.SECONDS)");
runnable = new Runnable() {
public void run() {
map.replace(null, "oldValue", "newValue");
}
};
assertRunnableThrowsNullPointerException(runnable, "replace(null, \"oldValue\", \"newValue\")");
runnable = new Runnable() {
public void run() {
map.replace("key", null, "newValue");
}
};
assertRunnableThrowsNullPointerException(runnable, "replace(\"key\", null, \"newValue\")");
runnable = new Runnable() {
public void run() {
map.replace("key", "oldValue", null);
}
};
assertRunnableThrowsNullPointerException(runnable, "replace(\"key\", \"oldValue\", null)");
runnable = new Runnable() {
public void run() {
map.replace(null, "value");
}
};
assertRunnableThrowsNullPointerException(runnable, "replace(null, \"value\")");
runnable = new Runnable() {
public void run() {
map.replace("key", null);
}
};
assertRunnableThrowsNullPointerException(runnable, "replace(\"key\", null)");
runnable = new Runnable() {
public void run() {
map.set(null, "value");
}
};
assertRunnableThrowsNullPointerException(runnable, "set(null, \"value\")");
runnable = new Runnable() {
public void run() {
map.set("key", null);
}
};
assertRunnableThrowsNullPointerException(runnable, "set(\"key\", null)");
runnable = new Runnable() {
public void run() {
map.set(null, "value", 1, SECONDS);
}
};
assertRunnableThrowsNullPointerException(runnable, "set(null, \"value\", 1, TimeUnit.SECONDS)");
runnable = new Runnable() {
public void run() {
map.set("key", null, 1, SECONDS);
}
};
assertRunnableThrowsNullPointerException(runnable, "set(\"key\", null, 1, TimeUnit.SECONDS)");
runnable = new Runnable() {
public void run() {
map.lock(null);
}
};
assertRunnableThrowsNullPointerException(runnable, "lock(null)");
runnable = new Runnable() {
public void run() {
map.lock(null, 1, SECONDS);
}
};
assertRunnableThrowsNullPointerException(runnable, "lock(null, 1, TimeUnit.SECONDS)");
runnable = new Runnable() {
public void run() {
map.isLocked(null);
}
};
assertRunnableThrowsNullPointerException(runnable, "isLocked(null)");
runnable = new Runnable() {
public void run() {
map.tryLock(null);
}
};
assertRunnableThrowsNullPointerException(runnable, "tryLock(null)");
runnable = new Runnable() {
public void run() {
try {
map.tryLock(null, 1, SECONDS);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
};
assertRunnableThrowsNullPointerException(runnable, "tryLock(null, 1, TimeUnit.SECONDS)");
runnable = new Runnable() {
public void run() {
map.unlock(null);
}
};
assertRunnableThrowsNullPointerException(runnable, "unlock(null)");
runnable = new Runnable() {
public void run() {
map.forceUnlock(null);
}
};
assertRunnableThrowsNullPointerException(runnable, "forceUnlock(null)");
runnable = new Runnable() {
public void run() {
map.getEntryView(null);
}
};
assertRunnableThrowsNullPointerException(runnable, "getEntryView(null)");
runnable = new Runnable() {
public void run() {
map.evict(null);
}
};
assertRunnableThrowsNullPointerException(runnable, "evict(null)");
runnable = new Runnable() {
public void run() {
map.executeOnKey(null, new SampleEntryProcessor());
}
};
assertRunnableThrowsNullPointerException(runnable, "executeOnKey(null, entryProcessor)");
final Map<String, String> mapWithNullKey = new HashMap<String, String>();
mapWithNullKey.put("key", "value");
mapWithNullKey.put(null, "nullKey");
runnable = new Runnable() {
public void run() {
map.putAll(mapWithNullKey);
}
};
assertRunnableThrowsNullPointerException(runnable, "map.putAll(mapWithNullKey)");
final Map<String, String> mapWithNullValue = new HashMap<String, String>();
mapWithNullValue.put("key", "value");
mapWithNullValue.put("nullValue", null);
runnable = new Runnable() {
public void run() {
map.putAll(mapWithNullValue);
}
};
assertRunnableThrowsNullPointerException(runnable, "map.putAll(mapWithNullValue)");
// we need to run the putAll() tests a second time passing in a map with more than (partitionCount * 3) entries,
// because MapProxySupport#putAllInternal() takes a different code path if there are more than that many entries
final int entryLimit = (INSTANCE_COUNT * 3) + 1;
for (int i = 0; i < entryLimit; i++) {
mapWithNullKey.put("key" + i, "value" + i);
}
runnable = new Runnable() {
public void run() {
map.putAll(mapWithNullKey);
}
};
assertRunnableThrowsNullPointerException(runnable, "map.putAll(mapWithNullKey)");
for (int i = 0; i < entryLimit; i++) {
mapWithNullValue.put("key" + i, "value" + i);
}
runnable = new Runnable() {
public void run() {
map.putAll(mapWithNullValue);
}
};
assertRunnableThrowsNullPointerException(runnable, "map.putAll(mapWithNullValue)");
}
public void assertRunnableThrowsNullPointerException(Runnable runnable, String description) {
boolean threwNpe = false;
try {
runnable.run();
} catch (NullPointerException npe) {
threwNpe = true;
}
assertTrue(description + " did not throw a NullPointerException.", threwNpe);
}
private static class SampleEntryProcessor implements EntryProcessor<Integer, Integer>, EntryBackupProcessor<Integer, Integer>,
Serializable {
private static final long serialVersionUID = -5735493325953375570L;
@Override
public Object process(Map.Entry<Integer, Integer> entry) {
entry.setValue(entry.getValue() + 1);
return true;
}
@Override
public EntryBackupProcessor<Integer, Integer> getBackupProcessor() {
return SampleEntryProcessor.this;
}
@Override
public void processBackup(Map.Entry<Integer, Integer> entry) {
entry.setValue(entry.getValue() + 1);
}
}
}