Apply patch and test case for HARMONY-6419 ([classlib][luni] Changes to IdentityHashMap entrySet doesn't reflect underlying map)
git-svn-id: https://svn.apache.org/repos/asf/harmony/enhanced/java/trunk@1043880 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/classlib/modules/luni/src/main/java/java/util/IdentityHashMap.java b/classlib/modules/luni/src/main/java/java/util/IdentityHashMap.java
index 053de1d..8627d03 100644
--- a/classlib/modules/luni/src/main/java/java/util/IdentityHashMap.java
+++ b/classlib/modules/luni/src/main/java/java/util/IdentityHashMap.java
@@ -83,8 +83,16 @@
private static final Object NULL_OBJECT = new Object(); //$NON-LOCK-1$
static class IdentityHashMapEntry<K, V> extends MapEntry<K, V> {
- IdentityHashMapEntry(K theKey, V theValue) {
- super(theKey, theValue);
+
+ final Object iKey;
+
+ final Object[] elementData;
+
+ IdentityHashMapEntry(K theKey, V theValue, Object[] elementData) {
+ super((K) theKey == NULL_OBJECT ? null : theKey,
+ (V) theValue == NULL_OBJECT ? null : theValue);
+ iKey = theKey;
+ this.elementData = elementData;
}
@Override
@@ -98,7 +106,7 @@
return true;
}
if (object instanceof Map.Entry) {
- Map.Entry<?, ?> entry = (Map.Entry) object;
+ Map.Entry<?, ?> entry = (Map.Entry<?, ?>) object;
return (key == entry.getKey()) && (value == entry.getValue());
}
return false;
@@ -114,6 +122,14 @@
public String toString() {
return key + "=" + value; //$NON-NLS-1$
}
+
+ public V setValue(V object) {
+ int index = findIndex(iKey, elementData);
+ if (elementData[index] == key) {
+ elementData[index + 1] = object;
+ }
+ return super.setValue(object);
+ }
}
static class IdentityHashMapIterator<E, KT, VT> implements Iterator<E> {
@@ -208,7 +224,7 @@
@Override
public boolean remove(Object object) {
if (contains(object)) {
- associatedMap.remove(((Map.Entry) object).getKey());
+ associatedMap.remove(((Map.Entry<?, ?>) object).getKey());
return true;
}
return false;
@@ -218,7 +234,7 @@
public boolean contains(Object object) {
if (object instanceof Map.Entry) {
IdentityHashMapEntry<?, ?> entry = associatedMap
- .getEntry(((Map.Entry) object).getKey());
+ .getEntry(((Map.Entry<?, ?>) object).getKey());
// we must call equals on the entry obtained from "this"
return entry != null && entry.equals(object);
}
@@ -397,24 +413,15 @@
*/
@SuppressWarnings("unchecked")
private IdentityHashMapEntry<K, V> getEntry(int index) {
- Object key = elementData[index];
- Object value = elementData[index + 1];
-
- if (key == NULL_OBJECT) {
- key = null;
- }
- if (value == NULL_OBJECT) {
- value = null;
- }
-
- return new IdentityHashMapEntry<K, V>((K) key, (V) value);
+ return new IdentityHashMapEntry<K, V>((K) elementData[index],
+ (V) elementData[index + 1], elementData);
}
/**
* Returns the index where the key is found at, or the index of the next
* empty spot if the key is not found in this table.
*/
- private int findIndex(Object key, Object[] array) {
+ private static int findIndex(Object key, Object[] array) {
int length = array.length;
int index = getModuloHash(key, length);
int last = (index + length - 2) % length;
@@ -431,7 +438,7 @@
return index;
}
- private int getModuloHash(Object key, int length) {
+ private static int getModuloHash(Object key, int length) {
return ((System.identityHashCode(key) & 0x7FFFFFFF) % (length / 2)) * 2;
}
@@ -729,7 +736,7 @@
return true;
}
if (object instanceof Map) {
- Map<?, ?> map = (Map) object;
+ Map<?, ?> map = (Map<?, ?>) object;
if (size() != map.size()) {
return false;
}
@@ -789,7 +796,7 @@
stream.writeInt(size);
Iterator<?> iterator = entrySet().iterator();
while (iterator.hasNext()) {
- MapEntry<?, ?> entry = (MapEntry) iterator.next();
+ MapEntry<?, ?> entry = (MapEntry<?, ?>) iterator.next();
stream.writeObject(entry.key);
stream.writeObject(entry.value);
}
diff --git a/classlib/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/util/IdentityHashMapTest.java b/classlib/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/util/IdentityHashMapTest.java
index 83ef5e0..4363fe0 100644
--- a/classlib/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/util/IdentityHashMapTest.java
+++ b/classlib/modules/luni/src/test/api/common/org/apache/harmony/luni/tests/java/util/IdentityHashMapTest.java
@@ -25,6 +25,7 @@
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
+import java.util.Map.Entry;
import org.apache.harmony.testframework.serialization.SerializationTest;
import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert;
@@ -409,6 +410,25 @@
assertEquals(cloneHashMap, ((IdentityHashMap) cloneHashMap)
.get((Object) null));
}
+
+ /*
+ * Regression test for HARMONY-6419
+ */
+ public void test_underlyingMap() {
+ IdentityHashMap<String, String> ihm = new IdentityHashMap<String, String>();
+ String key = "key";
+ String value = "value";
+ ihm.put(key, value);
+
+ Set<Entry<String, String>> set = ihm.entrySet();
+ assertEquals(1, set.size());
+
+ Entry<String, String> entry = set.iterator().next();
+
+ String newValue = "newvalue";
+ entry.setValue(newValue);
+ assertSame(newValue, ihm.get(key));
+ }
// comparator for IdentityHashMap objects
private static final SerializableAssert COMPARATOR = new SerializableAssert() {