package org.infinispan.util;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
import static org.testng.AssertJUnit.assertNull;
import static org.testng.AssertJUnit.assertTrue;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.infinispan.commons.equivalence.ByteArrayEquivalence;
import org.infinispan.commons.equivalence.Equivalence;
import org.infinispan.commons.equivalence.EquivalentHashMap;
import org.testng.annotations.Test;
/**
* Tests that {@link EquivalentHashMap} is functionally correct.
*
* @author Galder ZamarreƱo
* @since 5.3
*/
@Test(groups = "functional", testName = "util.EquivalentHashMapTest")
public class EquivalentHashMapTest {
protected static final Equivalence<byte[]> EQUIVALENCE =
new DebugByteArrayEquivalence();
public void testJdkMapExpectations() {
byteArrayGet(createStandardConcurrentMap(), false);
byteArrayContainsKey(createStandardConcurrentMap(), false);
byteArrayRemove(createStandardConcurrentMap(), false);
byteArrayPutSameValueTwice(createStandardConcurrentMap(), false);
byteArrayPutAll(createStandardConcurrentMap(), 3);
byteArrayContainsValue(createStandardConcurrentMap(), false);
byteArrayEquals(createStandardConcurrentMap(), createStandardConcurrentMap(), false);
byteArrayEntryEquality(createStandardConcurrentMap(), createStandardConcurrentMap(), false);
byteArrayValuesContains(createStandardConcurrentMap(), false);
byteArrayValuesRemove(createStandardConcurrentMap(), false);
byteArrayKeySetContains(createStandardConcurrentMap(), false);
byteArrayKeySetRemove(createStandardConcurrentMap(), false);
}
public void testByteArrayGet() {
byteArrayGet(createComparingConcurrentMap(), true);
}
public void testByteArrayContainsKey() {
byteArrayContainsKey(createComparingConcurrentMap(), true);
}
public void testByteArrayRemove() {
byteArrayRemove(createComparingConcurrentMap(), true);
}
public void testByteArrayPutSameValueTwice() {
byteArrayPutSameValueTwice(createComparingConcurrentMap(), true);
}
public void testByteArrayPutAll() {
byteArrayPutAll(createComparingConcurrentMap(), 2);
}
public void testByteArrayContainsValue() {
byteArrayContainsValue(createComparingConcurrentMap(), true);
}
public void testByteArrayEquals() {
byteArrayEquals(createComparingConcurrentMap(), createComparingConcurrentMap(), true);
}
public void testByteArrayEntryEquality() {
byteArrayEntryEquality(createComparingConcurrentMap(), createComparingConcurrentMap(), true);
}
public void testByteArrayValuesContains() {
byteArrayValuesContains(createComparingConcurrentMap(), true);
}
public void testByteArrayValuesRemove() {
byteArrayValuesRemove(createComparingConcurrentMap(), true);
}
public void testByteArrayEntrySetContains() {
byteArrayEntrySetContains(createComparingConcurrentMap(), createComparingConcurrentMap(), true);
}
public void testByteArrayEntrySetRemove() {
byteArrayEntrySetRemove(createComparingConcurrentMap(), createComparingConcurrentMap(), true);
}
public void testByteArrayKeySetContains() {
byteArrayKeySetContains(createComparingConcurrentMap(), true);
}
public void testByteArrayKeySetRemove() {
byteArrayKeySetRemove(createComparingConcurrentMap(), true);
}
protected void byteArrayGet(
Map<byte[], byte[]> map, boolean expectFound) {
byte[] key = {1, 2, 3};
byte[] value = {4, 5, 6};
map.put(key, value);
byte[] lookupKey = {1, 2, 3}; // on purpose, different instance required
if (expectFound)
assertTrue(String.format(
"Expected key=%s to return value=%s", str(lookupKey), str(value)),
Arrays.equals(value, map.get(lookupKey)));
else
assertNull(map.get(lookupKey));
}
protected void byteArrayContainsKey(
Map<byte[], byte[]> map, boolean expectFound) {
byte[] key = {1, 2, 3};
byte[] value = {4, 5, 6};
map.put(key, value);
byte[] lookupKey = {1, 2, 3}; // on purpose, different instance required
if (expectFound)
assertTrue(String.format(
"Expected key=%s to be in collection", str(lookupKey)),
map.containsKey(lookupKey));
else
assertNull(map.get(lookupKey));
}
protected void byteArrayRemove(
Map<byte[], byte[]> map, boolean expectRemove) {
byte[] key = {1, 2, 3};
byte[] value = {4, 5, 6};
map.put(key, value);
byte[] removeKey = {1, 2, 3}; // on purpose, different instance required
if (expectRemove)
assertTrue(String.format(
"Expected key=%s to be removed", str(removeKey)),
Arrays.equals(value, map.remove(removeKey)));
else
assertNull(map.get(removeKey));
}
protected void byteArrayPutSameValueTwice(
Map<byte[], byte[]> map, boolean expectFound) {
byte[] key = {1, 2, 3};
byte[] value = {4, 5, 6};
map.put(key, value);
byte[] putKey = {1, 2, 3}; // on purpose, different instance required
byte[] sameValue = {4, 5, 6}; // on purpose, different instance required
if (expectFound)
assertTrue(String.format(
"Expected putting %s again on key=%s to return value=%s",
str(sameValue), str(putKey), str(value)),
Arrays.equals(value, map.put(putKey, sameValue)));
else
assertNull(map.put(putKey, sameValue));
}
protected void byteArrayPutAll(
Map<byte[], byte[]> map, int expectCount) {
byte[] key = {1, 2, 3};
byte[] value = {4, 5, 6};
map.put(key, value);
Map<byte[], byte[]> data = new HashMap<byte[], byte[]>();
data.put(new byte[]{1, 2, 3}, new byte[]{7, 8, 9});
data.put(new byte[]{11, 22, 33}, new byte[]{44, 55, 66});
map.putAll(data);
assertEquals(expectCount, map.size());
}
protected void byteArrayContainsValue(
Map<byte[], byte[]> map, boolean expectFound) {
byte[] key = {1, 2, 3};
byte[] value = {4, 5, 6};
map.put(key, value);
byte[] lookupValue = {4, 5, 6}; // on purpose, different instance required
if (expectFound)
assertTrue(String.format(
"Expected value=%s lookup to return value=%s", str(lookupValue), str(value)),
map.containsValue(lookupValue));
else
assertFalse(map.containsValue(lookupValue));
}
protected void byteArrayEquals(Map<byte[], byte[]> map1,
Map<byte[], byte[]> map2, boolean expectEquals) {
byte[] key = {11, 22, 33};
map1.put(new byte[]{1, 2, 3}, new byte[]{4, 5, 6});
map1.put(key, new byte[]{7, 8, 9});
map2.put(new byte[]{1, 2, 3}, new byte[]{4, 5, 6});
map2.put(key, new byte[]{7, 8, 9});
if (expectEquals) {
assertEquals(map1, map2);
assertEquals(map1.hashCode(), map2.hashCode());
} else
assertFalse(String.format(
"Expected map1=%s to be distinct to map2=%s", map1.toString(), map2.toString()),
map1.equals(map2));
}
protected void byteArrayEntryEquality(Map<byte[], byte[]> map1,
Map<byte[], byte[]> map2, boolean expectEquals) {
map1.put(new byte[]{1, 2, 3}, new byte[]{4, 5, 6});
map2.put(new byte[]{1, 2, 3}, new byte[]{4, 5, 6});
Map.Entry<byte[], byte[]> entry1 = map1.entrySet().iterator().next();
Map.Entry<byte[], byte[]> entry2 = map2.entrySet().iterator().next();
if (expectEquals) {
assertEquals(entry1, entry2);
assertEquals(entry1.hashCode(), entry2.hashCode());
} else {
assertFalse(String.format(
"Expected entry1=%s to be distinct to entry2=%s", entry1, entry2),
entry1.equals(entry2));
}
}
protected void byteArrayValuesContains(
Map<byte[], byte[]> map, boolean expectContains) {
byte[] key = {1, 2, 3};
byte[] value = {4, 5, 6};
map.put(key, value);
byte[] containsValue = {4, 5, 6}; // on purpose, different instance required
Collection<byte[]> values = map.values();
if (expectContains)
assertTrue(String.format(
"Expected value=%s to be contained in values=%s", str(containsValue), values),
values.contains(containsValue));
else
assertFalse(values.contains(containsValue));
}
protected void byteArrayValuesRemove(
Map<byte[], byte[]> map, boolean expectRemove) {
byte[] key = {1, 2, 3};
byte[] value = {4, 5, 6};
map.put(key, value);
byte[] removeValue = {4, 5, 6}; // on purpose, different instance required
Collection<byte[]> values = map.values();
if (expectRemove)
assertTrue(String.format(
"Expected value=%s to be removed from values=%s", str(removeValue), values),
values.remove(removeValue));
else
assertFalse(values.remove(removeValue));
}
protected void byteArrayEntrySetContains(Map<byte[], byte[]> map1,
Map<byte[], byte[]> map2, boolean expectContains) {
map1.put(new byte[]{1, 2, 3}, new byte[]{4, 5, 6});
map2.put(new byte[]{1, 2, 3}, new byte[]{4, 5, 6});
Set<Map.Entry<byte[],byte[]>> entries1 = map1.entrySet();
Set<Map.Entry<byte[],byte[]>> entries2 = map2.entrySet();
Map.Entry<byte[], byte[]> entry1 = entries1.iterator().next();
if (expectContains)
assertTrue(String.format(
"Expected entry=%s to be contained in entries=%s", entry1, entries2),
entries2.contains(entry1));
else
assertFalse(entries2.contains(entry1));
}
protected void byteArrayEntrySetRemove(Map<byte[], byte[]> map1,
Map<byte[], byte[]> map2, boolean expectRemove) {
map1.put(new byte[]{1, 2, 3}, new byte[]{4, 5, 6});
map2.put(new byte[]{1, 2, 3}, new byte[]{4, 5, 6});
Set<Map.Entry<byte[],byte[]>> entries1 = map1.entrySet();
Set<Map.Entry<byte[],byte[]>> entries2 = map2.entrySet();
Map.Entry<byte[], byte[]> entry1 = entries1.iterator().next();
if (expectRemove)
assertTrue(String.format(
"Expected entry=%s to be removed from entries=%s", entry1, entries2),
entries2.remove(entry1));
else
assertFalse(entries2.remove(entry1));
}
protected void byteArrayKeySetContains(
Map<byte[], byte[]> map, boolean expectContains) {
byte[] key = {1, 2, 3};
byte[] value = {4, 5, 6};
map.put(key, value);
byte[] containsKey = {1, 2, 3}; // on purpose, different instance required
Set<byte[]> keys = map.keySet();
if (expectContains)
assertTrue(String.format(
"Expected key=%s to be contained in keys=%s", str(containsKey), keys),
keys.contains(containsKey));
else
assertFalse(keys.contains(containsKey));
}
protected void byteArrayKeySetRemove(
Map<byte[], byte[]> map, boolean expectRemove) {
byte[] key = {1, 2, 3};
byte[] value = {4, 5, 6};
map.put(key, value);
byte[] removeKey = {1, 2, 3}; // on purpose, different instance required
Set<byte[]> keys = map.keySet();
if (expectRemove)
assertTrue(String.format(
"Expected value=%s to be removed from keys=%s", str(removeKey), keys),
keys.remove(removeKey));
else
assertFalse(keys.remove(removeKey));
}
protected Map<byte[], byte[]> createStandardConcurrentMap() {
return new HashMap<byte[], byte[]>();
}
protected Map<byte[], byte[]> createComparingConcurrentMap() {
return new EquivalentHashMap<byte[], byte[]>(EQUIVALENCE, EQUIVALENCE);
}
protected String str(byte[] array) {
// Ignore IDE warning about hashCode() call!!
return array != null
? Arrays.toString(array) + "@" + Integer.toHexString(array.hashCode())
: "null";
}
private static class DebugByteArrayEquivalence implements Equivalence<byte[]> {
final Equivalence<byte[]> delegate = ByteArrayEquivalence.INSTANCE;
@Override
public int hashCode(Object obj) {
return delegate.hashCode(obj);
}
@Override
public boolean equals(byte[] obj, Object otherObj) {
return delegate.equals(obj, otherObj);
}
@Override
public String toString(Object obj) {
return delegate.toString(obj) + "@" + Integer.toHexString(obj.hashCode());
}
@Override
public boolean isComparable(Object obj) {
return delegate.isComparable(obj);
}
@Override
public int compare(byte[] obj, byte[] otherObj) {
return delegate.compare(obj, otherObj);
}
}
}