Replaced the HashMap implementation with a faster JSNI one.
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@381 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/super/com/google/gwt/emul/java/util/AbstractMap.java b/user/super/com/google/gwt/emul/java/util/AbstractMap.java
index 7293bf0..4d64ea9 100644
--- a/user/super/com/google/gwt/emul/java/util/AbstractMap.java
+++ b/user/super/com/google/gwt/emul/java/util/AbstractMap.java
@@ -16,7 +16,7 @@
package java.util;
/**
- * Abstract base class for map implementations.
+ * See Sun's JDK 1.4 Javadoc for documentation.
*/
public abstract class AbstractMap implements Map {
@@ -47,18 +47,15 @@
if (obj == this) {
return true;
}
-
if (!(obj instanceof Map)) {
return false;
}
-
Map otherMap = ((Map) obj);
Set keys = keySet();
Set otherKeys = otherMap.keySet();
if (!keys.equals(otherKeys)) {
return false;
}
-
for (Iterator iter = keys.iterator(); iter.hasNext();) {
Object key = iter.next();
Object value = get(key);
@@ -67,7 +64,6 @@
return false;
}
}
-
return true;
}
@@ -125,7 +121,10 @@
}
public void putAll(Map t) {
- throw new UnsupportedOperationException(MSG_CANNOT_MODIFY);
+ for (Iterator iter = t.entrySet().iterator(); iter.hasNext();) {
+ Map.Entry e = (Map.Entry) iter.next();
+ put(e.getKey(), e.getValue());
+ }
}
public Object remove(Object key) {
diff --git a/user/super/com/google/gwt/emul/java/util/HashMap.java b/user/super/com/google/gwt/emul/java/util/HashMap.java
index 0835c2d..f50574f 100644
--- a/user/super/com/google/gwt/emul/java/util/HashMap.java
+++ b/user/super/com/google/gwt/emul/java/util/HashMap.java
@@ -13,20 +13,58 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
+
package java.util;
-/**
- * Implements a hash table mapping object keys onto object values.
- */
-public class HashMap extends AbstractMap implements Map, Cloneable {
+import com.google.gwt.core.client.JavaScriptObject;
- private static class ImplMapEntry implements Map.Entry {
- private boolean inUse;
+/**
+ *
+ * See Sun's JDK 1.4 documentation for documentation on the <code>HashMap</code>
+ * API.
+ *
+ * This implementation of <code>HashMap</code> uses JavaScript native data
+ * structures to provide high performance in web mode, using string keys to
+ * index strings, and sparse int keys (via hashCode()) to index everything else.
+ */
+public class HashMap extends AbstractMap {
+ /*
+ * Implementation notes:
+ * String keys must be handled specially because we need only store one value
+ * for a given string key.
+ * String keys can collide with integer ones, as JavaScript treats '0' and 0
+ * as the same key. We resolve this by appending an 'S' on each string key.
+ * Integer keys are used for everything but Strings, as we get an integer by
+ * taking the hashcode, and storing the value there. Since several keys
+ * may have the same hashcode, we store a list of key/value pairs at the
+ * index of the hashcode. Javascript arrays are sparse, so this usage costs
+ * nothing in performance. Also, String and integer keys can coexist in the
+ * same data structure, which reduces storage overhead for small HashMaps.
+ * Things to pursue:
+ * Benchmarking shared data store (with the 'S' append) vs one structure for
+ * Strings and another for everything else).
+ * Benchmarking the effect of gathering the common parts of get/put/remove
+ * into a shared method. These methods would have several parameters, and
+ * some extra control flow.
+ */
+
+ /**
+ * Implementation of <code>HashMap</code> entry.
+ */
+ private static class EntryImpl implements Map.Entry {
private Object key;
private Object value;
+ /**
+ * Constructor for <code>EntryImpl</code>.
+ */
+ public EntryImpl(Object key, Object value) {
+ this.key = key;
+ this.value = value;
+ }
+
public boolean equals(Object a) {
if (a instanceof Map.Entry) {
Map.Entry s = (Map.Entry) a;
@@ -46,6 +84,9 @@
return value;
}
+ /**
+ * Calculate the hash code using Sun's specified algorithm.
+ */
public int hashCode() {
int keyHash = 0;
int valueHash = 0;
@@ -64,6 +105,13 @@
return old;
}
+ public String toString() {
+ return getKey() + "=" + getValue();
+ }
+
+ /**
+ * Checks to see of a == b correctly handling the case where a is null.
+ */
private boolean equalsWithNullCheck(Object a, Object b) {
if (a == b) {
return true;
@@ -74,343 +122,372 @@
}
}
}
+
+ /**
+ * Iterator for <code>EntrySetImpl</code>.
+ */
+ private final class EntrySetImplIterator implements Iterator {
+ Object last = null;
- private class ImplMapEntryIterator implements Iterator {
+ private final Iterator iter;
/**
- * Always points at the next full slot; equal to <code>entries.length</code>
- * if we're at the end.
+ * Constructor for <code>EntrySetIterator</code>.
*/
- private int i = 0;
-
- /**
- * Always points to the last element returned by next, or <code>-1</code>
- * if there is no last element.
- */
- private int last = -1;
-
- public ImplMapEntryIterator() {
- maybeAdvanceToFullSlot();
+ public EntrySetImplIterator() {
+ final List l = new ArrayList();
+ addAllFromJavascriptObject(l, map, BOTH_POS);
+ final Iterator lstIter = l.iterator();
+ this.iter = lstIter;
}
public boolean hasNext() {
- return (i < entries.length);
+ return iter.hasNext();
}
public Object next() {
- if (!hasNext()) {
- throw new NoSuchElementException();
- }
- last = i++;
- maybeAdvanceToFullSlot();
- return entries[last];
+ last = iter.next();
+ return last;
}
public void remove() {
- if (last < 0) {
- throw new IllegalStateException();
+ if (last == null) {
+ throw new IllegalStateException("Must call next() before remove().");
+ } else {
+ iter.remove();
+ HashMap.this.remove(((Entry) last).getKey());
}
- // do the remove
- entries[last].inUse = false;
- --fullSlots;
- last = -1;
}
+ }
- /**
- * Ensure that <code>i</code> points at a full slot; or is equal to
- * <code>entries.length</code> if we're at the end.
- */
- private void maybeAdvanceToFullSlot() {
- for (; i < entries.length; ++i) {
- if (entries[i] != null && entries[i].inUse) {
- return;
+ /**
+ * Keys are stored in the first position of each pair within the JavaScript
+ * dictionary. This constant encodes that fact.
+ */
+ private static final int KEYS_POS = 0;
+
+ /**
+ * Values are stored in the second position of each pair within the JavaScript
+ * dictionary. This constant encodes that fact.
+ */
+ private static final int VALUES_POS = 1;
+
+ /**
+ * This constant is used when new mapping entries should be generated from the
+ * JavaScript item.
+ */
+ private static final int BOTH_POS = 2;
+
+ protected static Map.Entry createEntry(Object key, Object value) {
+ return new EntryImpl(key, value);
+ }
+
+ // Used by JSNI for key processing, not private to avoid eclipse "unused
+ // method" warning.
+ static String asString(Object o) {
+ // All keys must either be entirely numeric, or end with 'S' or be
+ // the sentinel value "null".
+
+ if (o instanceof String) {
+ // Mark all string keys so they do not conflict with numeric ones.
+ return ((String) o) + "S";
+ } else if (o == null) {
+ return "null";
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Finds the <code>JavaScriptObject</code> associated with the given
+ * non-string key. Used in JSNI.
+ */
+ private static native JavaScriptObject findNode(HashMap me, Object key) /*-{
+ var KEYS_POS = 0;
+ var map = me.@java.util.HashMap::map;
+ var k = key.@java.lang.Object::hashCode()();
+ var candidates = map[k];
+ if (candidates != null) {
+ for (var index in candidates) {
+ var candidate = candidates[index];
+ if (candidate[KEYS_POS].@java.lang.Object::equals(Ljava/lang/Object;)(key)) {
+ return [k, index];
}
}
}
- }
+ return null;
+ }-*/;
/**
- * Number of physically empty slots in {@link #entries}.
+ * Underlying JavaScript map.
*/
- private int emptySlots;
+ private JavaScriptObject map;
- /**
- * The underlying data store.
- */
- private ImplMapEntry[] entries;
-
- /**
- * Number of logically full slots in {@link #entries}.
- */
- private int fullSlots;
-
- /**
- * A number between 0 and 1, exclusive. Used to calculated the new
- * {@link #threshold} at which this map will be rehashed.
- */
- private float loadFactor;
-
- /**
- * Always equal to {@link #entries}.length * {@link #loadFactor}. When the
- * number of non-empty slots exceeds this number, a rehash is performed.
- */
- private int threshold;
+ private int currentSize = 0;
public HashMap() {
- this(16);
+ init();
}
- public HashMap(int initialCapacity) {
- this(initialCapacity, 0.75f);
+ public HashMap(HashMap toBeCopied) {
+ this();
+ this.putAll(toBeCopied);
}
- public HashMap(int initialCapacity, float loadFactor) {
- if (initialCapacity < 0 || loadFactor <= 0) {
+ public HashMap(int ignored) {
+ // This implementation of HashMap has no need of initial capacities.
+ this(ignored, 0);
+ }
+
+ public HashMap(int ignored, float alsoIgnored) {
+ this();
+ // This implementation of HashMap has no need of load factors or capacities.
+ if (ignored < 0 || alsoIgnored < 0) {
throw new IllegalArgumentException(
"initial capacity was negative or load factor was non-positive");
}
-
- if (initialCapacity == 0) {
- // Rather than have to check for 0 every time we rehash, bumping 0 to 1
- // here.
- initialCapacity = 1;
- }
-
- /*
- * This implementation does not used linked lists in each slot. It is
- * physically impossible to store more entries than we have slots, so
- * fLoadFactor must be < 1 or we'll run out of slots.
- */
- if (loadFactor > 0.9f) {
- loadFactor = 0.9f;
- }
-
- this.loadFactor = loadFactor;
- realloc(initialCapacity);
- }
-
- public HashMap(Map m) {
- this(m.size());
- putAll(m);
}
public void clear() {
- fullSlots = 0;
- realloc(entries.length);
+ init();
+ currentSize = 0;
}
public Object clone() {
return new HashMap(this);
}
- public boolean containsKey(Object key) {
- int i = implFindSlot(key);
- if (i >= 0) {
- ImplMapEntry entry = entries[i];
- if (entry != null && entry.inUse) {
- return true;
- }
+ public native boolean containsKey(Object key) /*-{
+ var k = @java.util.HashMap::asString(Ljava/lang/Object;)(key);
+ if (k == null) {
+ var location = @java.util.HashMap::findNode(Ljava/util/HashMap;Ljava/lang/Object;)(this, key);
+ return (location != null);
+ } else {
+ return this.@java.util.HashMap::map[k] !== undefined;
}
- return false;
- }
+ }-*/;
public boolean containsValue(Object value) {
- return super.containsValue(value);
+ return values().contains(value);
}
public Set entrySet() {
return new AbstractSet() {
+ public boolean contains(Object entryObj) {
+ Entry entry = (Entry) entryObj;
+ if (entry != null) {
+ Object key = entry.getKey();
+ Object value = entry.getValue();
+ // If the value is null, we only want to return true if the found
+ // value equals null AND the HashMap
+ // contains the given key.
+ if (value != null || HashMap.this.containsKey(key)) {
+ Object foundValue = HashMap.this.get(key);
+ if (value == null) {
+ return foundValue == null;
+ } else {
+ return value.equals(foundValue);
+ }
+ }
+ }
+ return false;
+ }
+
public Iterator iterator() {
- return new ImplMapEntryIterator();
+ return new EntrySetImplIterator();
+ }
+
+ public boolean remove(Object entry) {
+ if (contains(entry)) {
+ Object key = ((Entry) entry).getKey();
+ HashMap.this.remove(key);
+ return true;
+ } else {
+ return false;
+ }
}
public int size() {
- return fullSlots;
+ return HashMap.this.size();
}
};
}
- public Object get(Object key) {
- int i = implFindSlot(key);
- if (i >= 0) {
- ImplMapEntry entry = entries[i];
- if (entry != null && entry.inUse) {
- return entry.value;
+ public native Object get(Object key) /*-{
+ var KEYS_POS = 0;
+ var VALUES_POS = 1;
+ var k = @java.util.HashMap::asString(Ljava/lang/Object;)(key);
+ if (k != null) {
+ var current = this.@java.util.HashMap::map[k];
+ if (current === undefined) {
+ return null;
+ } else {
+ return current;
+ }
+ } else {
+ k = key.@java.lang.Object::hashCode()();
+ }
+ var candidates = this.@java.util.HashMap::map[k];
+ if (candidates == null) {
+ return null;
+ }
+
+ // Used because candidates may develop holes as deletions are performed.
+ for (var i in candidates) {
+ if (candidates[i][KEYS_POS].@java.lang.Object::equals(Ljava/lang/Object;)(key)) {
+ return candidates[i][VALUES_POS];
}
}
- return null;
+ return null;
+ }-*/;
+
+ public boolean isEmpty() {
+ return size() == 0;
}
- public int hashCode() {
- int accum = 0;
- Iterator elements = entrySet().iterator();
- while (elements.hasNext()) {
- accum += elements.next().hashCode();
+ public native Object put(Object key, Object value) /*-{
+ var KEYS_POS = 0;
+ var VALUES_POS = 1;
+ var previous = null;
+ var k = @java.util.HashMap::asString(Ljava/lang/Object;)(key);
+ if (k != null) {
+ previous = this.@java.util.HashMap::map[k];
+ this.@java.util.HashMap::map[k] = value;
+ if (previous === undefined) {
+ this.@java.util.HashMap::currentSize++;
+ return null;
+ } else {
+ return previous;
+ }
+ } else {
+ k = key.@java.lang.Object::hashCode()();
}
- return accum;
- }
-
- public Set keySet() {
- return super.keySet();
- }
-
- public Object put(Object key, Object value) {
- /*
- * If the number of non-empty slots exceeds the threshold, rehash.
- */
- if ((entries.length - emptySlots) >= threshold) {
- implRehash();
+ var candidates = this.@java.util.HashMap::map[k];
+ if (candidates == null) {
+ candidates = [];
+ this.@java.util.HashMap::map[k] = candidates;
+ }
+
+ // Used because candidates may develop holes as deletions are performed.
+ for (var i in candidates) {
+ if (candidates[i][KEYS_POS].@java.lang.Object::equals(Ljava/lang/Object;)(key)) {
+ previous = candidates[i][VALUES_POS];
+ candidates[i] = [key, value];
+ return previous;
+ }
}
- return implPutNoRehash(key, value);
- }
+ this.@java.util.HashMap::currentSize++;
+ candidates[candidates.length] = [key,value];
+ return null;
+ }-*/;
- public void putAll(Map m) {
- Set entrySet = m.entrySet();
- for (Iterator iter = entrySet.iterator(); iter.hasNext();) {
- Map.Entry entry = (Map.Entry) iter.next();
+ public void putAll(Map otherMap) {
+ Iterator iter = otherMap.entrySet().iterator();
+ while (iter.hasNext()) {
+ Map.Entry entry = (Entry) iter.next();
put(entry.getKey(), entry.getValue());
}
}
- public Object remove(Object key) {
- int i = implFindSlot(key);
- if (i >= 0) {
- ImplMapEntry entry = entries[i];
- if (entry != null && entry.inUse) {
- entry.inUse = false;
- --fullSlots;
- return entry.getValue();
- }
- }
- return null;
- }
-
- public int size() {
- return fullSlots;
- }
-
- /**
- * Finds the i slot with the matching key or the first empty slot. This method
- * intentionally ignores whether or not an entry is marked "in use" because
- * the table implements "lazy deletion", meaning that every object keeps its
- * intrinsic location, whether or not it is considered still in the table or
- * not.
- *
- * @return the i of the slot in which either the entry having the key was
- * found or in which the entry would go; -1 if the hash table is
- * totally full
- */
- private int implFindSlot(Object key) {
- int hashCode = (key != null ? key.hashCode() : 7919);
- hashCode = (hashCode < 0 ? -hashCode : hashCode);
- int capacity = entries.length;
- int startIndex = (hashCode % capacity);
- int slotIndex = startIndex;
- int stopIndex = capacity;
- for (int i = 0; i < 2; ++i) {
- for (; slotIndex < stopIndex; ++slotIndex) {
- Map.Entry entry = entries[slotIndex];
- if (entry == null) {
- return slotIndex;
- }
-
- Object testKey = entry.getKey();
- if (key == null ? testKey == null : key.equals(testKey)) {
- return slotIndex;
- }
- }
-
- // Wrap around
- //
- slotIndex = 0;
- stopIndex = startIndex;
- }
- // The hash table is totally full and the matching item was not found.
- //
- return -1;
- }
-
- /**
- * Implements 'put' with the assumption that there will definitely be room for
- * the new item.
- */
- private Object implPutNoRehash(Object key, Object value) {
- // No need to check for (i == -1) because rehash would've made the array big
- // enough to find a slot
- int i = implFindSlot(key);
- if (entries[i] != null) {
- // Just updating the value that was already there.
- // Remember that the existing entry might have been deleted.
- //
- ImplMapEntry entry = entries[i];
-
- Object old = null;
- if (entry.inUse) {
- old = entry.value;
+ public native Object remove(Object key) /*-{
+ var VALUES_POS = 1;
+ var map = this.@java.util.HashMap::map;
+ var k = @java.util.HashMap::asString(Ljava/lang/Object;)(key);
+ var previous = null;
+ if (k != null) {
+ previous = map[k];
+ delete map[k];
+ if (previous !== undefined) {
+ this.@java.util.HashMap::currentSize--;
+ return previous;
} else {
- ++fullSlots;
+ return null;
}
-
- entry.value = value;
- entry.inUse = true;
- return old;
- } else {
- // This a brand new (key, value) pair.
- //
- ++fullSlots;
- --emptySlots;
- ImplMapEntry entry = new ImplMapEntry();
- entry.key = key;
- entry.value = value;
- entry.inUse = true;
- entries[i] = entry;
+ }
+ var location = @java.util.HashMap::findNode(Ljava/util/HashMap;Ljava/lang/Object;)(this, key);
+ if (location == null) {
return null;
}
+ this.@java.util.HashMap::currentSize--;
+ var hashCode = location[0];
+ var index = location[1];
+ var previous = map[hashCode][index][VALUES_POS];
+ map[hashCode].splice(index,1);
+ if (map[hashCode].length > 0) {
+ // Not the only cell for this hashCode, so no deletion.
+ return previous;
+ }
+ delete map[hashCode];
+ return previous;
+ }-*/;
+
+ public int size() {
+ return currentSize;
+ }
+
+ public Collection values() {
+ List values = new Vector();
+ addAllValuesFromJavascriptObject(values, map);
+ return values;
+ }
+
+ // Package protected to remove eclipse warning marker.
+ void addAllKeysFromJavascriptObject(Collection source,
+ JavaScriptObject javaScriptObject) {
+ addAllFromJavascriptObject(source, javaScriptObject, KEYS_POS);
}
/**
- * Implements a rehash. The underlying array store may or may not be doubled.
+ * Adds all keys, values, or entries to the collection depending upon
+ * typeToAdd.
*/
- private void implRehash() {
- // Save the old entry array.
- //
- ImplMapEntry[] oldEntries = entries;
-
- /*
- * Allocate a new entry array. If the actual number or full slots exceeds
- * the load factor, double the array size. Otherwise just rehash, clearing
- * out all the empty slots.
- */
- int capacity = oldEntries.length;
- if (fullSlots > threshold) {
- capacity *= 2;
- }
-
- realloc(capacity);
-
- // Now put all the in-use entries from the old array into the new array.
- //
- for (int i = 0, n = oldEntries.length; i < n; ++i) {
- ImplMapEntry oldEntry = oldEntries[i];
- if (oldEntry != null && oldEntry.inUse) {
- int slot = implFindSlot(oldEntry.key);
- // the array should be big enough to find a slot no matter what
- assert (slot >= 0);
- entries[slot] = oldEntry;
+ private native void addAllFromJavascriptObject(Collection source,
+ JavaScriptObject javaScriptObject, int typeToAdd)
+ /*-{
+ var KEYS_POS = 0;
+ var VALUES_POS = 1;
+ var BOTH_POS = 2;
+ var map = this.@java.util.HashMap::map;
+ for (var hashCode in javaScriptObject) {
+ var entry = null;
+ if (hashCode == "null" || hashCode.charAt(hashCode.length - 1) == 'S') {
+ var key = null;
+ if (typeToAdd != VALUES_POS && hashCode != "null") {
+ key = hashCode.substring(0, hashCode.length - 1);
+ }
+ if (typeToAdd == KEYS_POS) {
+ entry = key
+ } else if (typeToAdd == VALUES_POS) {
+ entry = map[hashCode];
+ } else if (typeToAdd == BOTH_POS) {
+ entry =
+ @java.util.HashMap::createEntry(Ljava/lang/Object;Ljava/lang/Object;)(
+ key, map[hashCode]);
+ }
+ source.@java.util.Collection::add(Ljava/lang/Object;)(entry);
+ } else {
+ var candidates = map[hashCode];
+ for (var index in candidates) {
+ if (typeToAdd != BOTH_POS) {
+ entry = candidates[index][typeToAdd];
+ } else {
+ entry =
+ @java.util.HashMap::createEntry(Ljava/lang/Object;Ljava/lang/Object;)(
+ candidates[index][0], candidates[index][1]);
+ }
+ source.@java.util.Collection::add(Ljava/lang/Object;)(entry);
+ }
}
}
+ }-*/;
+
+ private void addAllValuesFromJavascriptObject(Collection source,
+ JavaScriptObject javaScriptObject) {
+ addAllFromJavascriptObject(source, javaScriptObject, VALUES_POS);
}
- /**
- * Set entries to a new array of the given capacity. Automatically recomputes
- * threshold and emptySlots.
- *
- * @param capacity
- */
- private void realloc(int capacity) {
- threshold = (int) (capacity * loadFactor);
- emptySlots = capacity - fullSlots;
- entries = new ImplMapEntry[capacity];
- }
+ private native void init() /*-{
+ this.@java.util.HashMap::map = [];
+ }-*/;
}
diff --git a/user/test/com/google/gwt/emultest/java/util/HashMapTest.java b/user/test/com/google/gwt/emultest/java/util/HashMapTest.java
index f23929c..68eb8f9 100644
--- a/user/test/com/google/gwt/emultest/java/util/HashMapTest.java
+++ b/user/test/com/google/gwt/emultest/java/util/HashMapTest.java
@@ -1,13 +1,89 @@
-// Copyright 2006 Google Inc. All Rights Reserved.
+/*
+ * Copyright 2006 Google Inc.
+ *
+ * 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.google.gwt.emultest.java.util;
+import com.google.gwt.core.client.GWT;
+
+import org.apache.commons.collections.TestMap;
+
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
+import java.util.Map.Entry;
-public class HashMapTest extends EmulTestBase {
+/**
+ * Tests <code>HashMap</code>.
+ */
+public class HashMapTest extends TestMap {
+ private static final int CAPACITY_16 = 16;
+ private static final int CAPACITY_NEG_ONE_HALF = -1;
+ private static final int CAPACITY_ZERO = 0;
+ private static final Integer INTEGER_1 = new Integer(1);
+ private static final Integer INTEGER_11 = new Integer(11);
+ private static final Integer INTEGER_2 = new Integer(2);
+ private static final Integer INTEGER_22 = new Integer(22);
+ private static final Integer INTEGER_3 = new Integer(3);
+ private static final Integer INTEGER_33 = new Integer(33);
+ private static final Integer INTEGER_ZERO_KEY = new Integer(0);
+ private static final String INTEGER_ZERO_VALUE = "integer zero";
+ private static final String KEY_1 = "key1";
+ private static final String KEY_2 = "key2";
+ private static final String KEY_3 = "key3";
+ private static final String KEY_4 = "key4";
+ private static final String KEY_KEY = "key";
+ private static final String KEY_TEST_CONTAINS_KEY = "testContainsKey";
+ private static final String KEY_TEST_CONTAINS_VALUE = "testContainsValue";
+ private static final String KEY_TEST_ENTRY_SET = "testEntrySet";
+ private static final String KEY_TEST_GET = "testGet";
+ private static final String KEY_TEST_KEY_SET = "testKeySet";
+ private static final String KEY_TEST_PUT = "testPut";
+ private static final String KEY_TEST_REMOVE = "testRemove";
+ private static final float LOAD_FACTOR_NEG_ONE = -1.0F;
+ private static final float LOAD_FACTOR_ONE_HALF = 0.5F;
+ private static final float LOAD_FACTOR_ONE_TENTH = 0.1F;
+ private static final float LOAD_FACTOR_ZERO = 0.0F;
+ private static final Object ODD_ZERO_KEY = new Object() {
+ public int hashCode() {
+ return 0;
+ }
+ };
+ private static final String ODD_ZERO_VALUE = "odd zero";
+ private static final int SIZE_ONE = 1;
+ private static final int SIZE_THREE = 3;
+ private static final int SIZE_TWO = 2;
+ private static final int SIZE_ZERO = 0;
+ private static final String STRING_ZERO_KEY = "0";
+ private static final String STRING_ZERO_VALUE = "string zero";
+ private static final String VALUE_1 = "val1";
+ private static final String VALUE_2 = "val2";
+ private static final String VALUE_3 = "val3";
+ private static final String VALUE_4 = "val4";
+ private static final String VALUE_TEST_CONTAINS_DOES_NOT_EXIST = "does not exist";
+ private static final Integer VALUE_TEST_CONTAINS_KEY = new Integer(5);
+ private static final String VALUE_TEST_ENTRY_SET_1 = KEY_TEST_ENTRY_SET + " - value1";
+ private static final String VALUE_TEST_ENTRY_SET_2 = KEY_TEST_ENTRY_SET + " - value2";
+ private static final String VALUE_TEST_GET = KEY_TEST_GET + " - Value";
+ private static final String VALUE_TEST_KEY_SET = KEY_TEST_KEY_SET + " - value";
+ private static final String VALUE_TEST_PUT_1 = KEY_TEST_PUT + " - value 1";
+ private static final String VALUE_TEST_PUT_2 = KEY_TEST_PUT + " - value 2";
+ private static final String VALUE_TEST_REMOVE = KEY_TEST_REMOVE + " - value";
+ private static final String VALUE_VAL = "value";
+
/**
* Check the state of a newly constructed, empty HashMap.
*
@@ -37,6 +113,25 @@
return "com.google.gwt.emultest.EmulSuite";
}
+ public void testAddWatch() {
+ HashMap m = new HashMap();
+ m.put("watch", "watch");
+ assertEquals(m.get("watch"), "watch");
+ }
+
+ public void testAddEqualKeys() {
+ final HashMap expected = new HashMap();
+ assertEquals(expected.size(),0);
+ iterateThrough(expected);
+ expected.put(new Long(45), new Object());
+ assertEquals(expected.size(),1);
+ iterateThrough(expected);
+ expected.put(new Integer(45), new Object());
+ assertNotSame(new Integer(45), new Long(45));
+ assertEquals(expected.size(),2);
+ iterateThrough(expected);
+ }
+
/*
* Test method for 'java.util.HashMap.clear()'
*/
@@ -46,7 +141,7 @@
hashMap.put("Hello", "Bye");
assertFalse(hashMap.isEmpty());
- assertTrue(hashMap.size() == 1);
+ assertTrue(hashMap.size() == SIZE_ONE);
hashMap.clear();
assertTrue(hashMap.isEmpty());
@@ -68,17 +163,10 @@
assertTrue(dstMap.keySet().equals(srcMap.keySet()));
assertTrue(dstMap.entrySet().equals(srcMap.entrySet()));
- final String KEY1 = "1";
- final String VAL1 = "2";
- final String KEY2 = "3";
- final String VAL2 = "4";
- final String KEY3 = "5";
- final String VAL3 = "6";
-
// Check non-empty clone behavior
- srcMap.put(KEY1, VAL1);
- srcMap.put(KEY2, VAL2);
- srcMap.put(KEY3, VAL3);
+ srcMap.put(KEY_1, VALUE_1);
+ srcMap.put(KEY_2, VALUE_2);
+ srcMap.put(KEY_3, VALUE_3);
dstMap = (HashMap) srcMap.clone();
assertNotNull(dstMap);
assertEquals(dstMap.size(), srcMap.size());
@@ -92,20 +180,16 @@
* Test method for 'java.util.HashMap.containsKey(Object)'
*/
public void testContainsKey() {
- final String KEY = "testContainsKey";
- final Integer VAL = new Integer(5);
- final String NON_EXISTANT_KEY = "does not exist";
-
HashMap hashMap = new HashMap();
checkEmptyHashMapAssumptions(hashMap);
- assertFalse(hashMap.containsKey(KEY));
- hashMap.put(KEY, VAL);
- assertTrue(hashMap.containsKey(KEY));
- assertFalse(hashMap.containsKey(NON_EXISTANT_KEY));
+ assertFalse(hashMap.containsKey(KEY_TEST_CONTAINS_KEY));
+ hashMap.put(KEY_TEST_CONTAINS_KEY, VALUE_TEST_CONTAINS_KEY);
+ assertTrue(hashMap.containsKey(KEY_TEST_CONTAINS_KEY));
+ assertFalse(hashMap.containsKey(VALUE_TEST_CONTAINS_DOES_NOT_EXIST));
assertFalse(hashMap.containsKey(null));
- hashMap.put(null, VAL);
+ hashMap.put(null, VALUE_TEST_CONTAINS_KEY);
assertTrue(hashMap.containsKey(null));
}
@@ -113,20 +197,16 @@
* Test method for 'java.util.HashMap.containsValue(Object)'
*/
public void testContainsValue() {
- final String KEY = "testContainsValue";
- final Integer VAL = new Integer(5);
- final String NON_EXISTANT_KEY = "does not exist";
-
HashMap hashMap = new HashMap();
checkEmptyHashMapAssumptions(hashMap);
- assertFalse(hashMap.containsValue(VAL));
- hashMap.put(KEY, VAL);
- assertTrue(hashMap.containsValue(VAL));
- assertFalse(hashMap.containsValue(NON_EXISTANT_KEY));
+ assertFalse("check contains of empty map", hashMap.containsValue(VALUE_TEST_CONTAINS_KEY));
+ hashMap.put(KEY_TEST_CONTAINS_VALUE, VALUE_TEST_CONTAINS_KEY);
+ assertTrue("check contains of map with element", hashMap.containsValue(VALUE_TEST_CONTAINS_KEY));
+ assertFalse("check contains of map other element", hashMap.containsValue(VALUE_TEST_CONTAINS_DOES_NOT_EXIST));
assertFalse(hashMap.containsValue(null));
- hashMap.put(KEY, null);
+ hashMap.put(KEY_TEST_CONTAINS_VALUE, null);
assertTrue(hashMap.containsValue(null));
}
@@ -140,33 +220,44 @@
Set entrySet = hashMap.entrySet();
assertNotNull(entrySet);
- final String KEY = "testEntrySet";
- final String VAL1 = KEY + " - value1";
- final String VAL2 = KEY + " - value2";
-
// Check that the entry set looks right
- hashMap.put(KEY, VAL1);
+ hashMap.put(KEY_TEST_ENTRY_SET, VALUE_TEST_ENTRY_SET_1);
entrySet = hashMap.entrySet();
- assertEquals(entrySet.size(), 1);
+ assertEquals(entrySet.size(), SIZE_ONE);
Iterator itSet = entrySet.iterator();
Map.Entry entry = (Map.Entry) itSet.next();
- assertEquals(entry.getKey(), KEY);
- assertEquals(entry.getValue(), VAL1);
+ assertEquals(entry.getKey(), KEY_TEST_ENTRY_SET);
+ assertEquals(entry.getValue(), VALUE_TEST_ENTRY_SET_1);
- // Check that entries in the entryset are update correctly on overwrites
- hashMap.put(KEY, VAL2);
+ // Check that entries in the entrySet are update correctly on overwrites
+ hashMap.put(KEY_TEST_ENTRY_SET, VALUE_TEST_ENTRY_SET_2);
entrySet = hashMap.entrySet();
- assertEquals(entrySet.size(), 1);
+ assertEquals(entrySet.size(), SIZE_ONE);
itSet = entrySet.iterator();
entry = (Map.Entry) itSet.next();
- assertEquals(entry.getKey(), KEY);
- assertEquals(entry.getValue(), VAL2);
+ assertEquals(entry.getKey(), KEY_TEST_ENTRY_SET);
+ assertEquals(entry.getValue(), VALUE_TEST_ENTRY_SET_2);
// Check that entries are updated on removes
- hashMap.remove(KEY);
+ hashMap.remove(KEY_TEST_ENTRY_SET);
checkEmptyHashMapAssumptions(hashMap);
}
+ /*
+ * Used to test the entrySet remove method.
+ */
+ public void testEntrySetRemove() {
+ HashMap hashMap = new HashMap();
+ hashMap.put("A","B");
+ HashMap dummy = new HashMap();
+ dummy.put("A", "b");
+ Entry bogus = (Entry) dummy.entrySet().iterator().next();
+ Set entrySet = hashMap.entrySet();
+ boolean removed = entrySet.remove(bogus);
+ assertEquals(removed, false);
+ assertEquals(hashMap.get("A"), "B");
+ }
+
/*
* Test method for 'java.util.AbstractMap.equals(Object)'
*/
@@ -174,48 +265,43 @@
HashMap hashMap = new HashMap();
checkEmptyHashMapAssumptions(hashMap);
- final String KEY = "key";
- final String VAL = "val";
-
- hashMap.put(KEY, VAL);
+ hashMap.put(KEY_KEY, VALUE_VAL);
HashMap copyMap = (HashMap) hashMap.clone();
assertTrue(hashMap.equals(copyMap));
- hashMap.put(VAL, KEY);
+ hashMap.put(VALUE_VAL, KEY_KEY);
assertFalse(hashMap.equals(copyMap));
}
/*
- * Test method for 'java.lang.Object.finalize()'
+ * Test method for 'java.lang.Object.finalize()'.
*/
public void testFinalize() {
+ // no tests for finalize
}
/*
- * Test method for 'java.util.HashMap.get(Object)'
+ * Test method for 'java.util.HashMap.get(Object)'.
*/
public void testGet() {
- final String KEY = "testGet";
- final String VAL = KEY + " - Value";
-
HashMap hashMap = new HashMap();
checkEmptyHashMapAssumptions(hashMap);
-
- assertNull(hashMap.get(KEY));
- hashMap.put(KEY, VAL);
- assertNotNull(hashMap.get(KEY));
+
+ assertNull(hashMap.get(KEY_TEST_GET));
+ hashMap.put(KEY_TEST_GET, VALUE_TEST_GET);
+ assertNotNull(hashMap.get(KEY_TEST_GET));
assertNull(hashMap.get(null));
- hashMap.put(null, VAL);
+ hashMap.put(null, VALUE_TEST_GET);
assertNotNull(hashMap.get(null));
-
+
hashMap.put(null, null);
assertNull(hashMap.get(null));
}
/*
- * Test method for 'java.util.AbstractMap.hashCode()'
+ * Test method for 'java.util.AbstractMap.hashCode()'.
*/
public void testHashCode() {
HashMap hashMap = new HashMap();
@@ -223,14 +309,14 @@
// Check that hashCode changes
int hashCode1 = hashMap.hashCode();
- hashMap.put("key", "val");
+ hashMap.put(KEY_KEY, VALUE_VAL);
int hashCode2 = hashMap.hashCode();
assertTrue(hashCode1 != hashCode2);
}
/*
- * Test method for 'java.util.HashMap.HashMap()'
+ * Test method for 'java.util.HashMap.HashMap()'.
*/
public void testHashMap() {
HashMap hashMap = new HashMap();
@@ -241,17 +327,17 @@
* Test method for 'java.util.HashMap.HashMap(int)'
*/
public void testHashMapInt() {
- final int CAPACITY = 16;
- HashMap hashMap = new HashMap(CAPACITY);
+ HashMap hashMap = new HashMap(CAPACITY_16);
checkEmptyHashMapAssumptions(hashMap);
// TODO(mmendez): how do we verify capacity?
boolean failed = true;
try {
- new HashMap(-1);
+ new HashMap(-SIZE_ONE);
} catch (Throwable ex) {
- if (ex instanceof IllegalArgumentException)
+ if (ex instanceof IllegalArgumentException) {
failed = false;
+ }
}
if (failed) {
@@ -266,10 +352,8 @@
* Test method for 'java.util.HashMap.HashMap(int, float)'
*/
public void testHashMapIntFloat() {
- final int CAPACITY = 16;
- final float LOAD_FACTOR = 0.5F;
- HashMap hashMap = new HashMap(CAPACITY, LOAD_FACTOR);
+ HashMap hashMap = new HashMap(CAPACITY_16, LOAD_FACTOR_ONE_HALF);
checkEmptyHashMapAssumptions(hashMap);
// TODO(mmendez): how do we verify capacity and load factor?
@@ -277,10 +361,11 @@
// Test new HashMap(-1, 0.0F)
boolean failed = true;
try {
- new HashMap(-1, 0.0F);
+ new HashMap(CAPACITY_NEG_ONE_HALF, LOAD_FACTOR_ZERO);
} catch (Throwable ex) {
- if (ex instanceof IllegalArgumentException)
+ if (ex instanceof IllegalArgumentException) {
failed = false;
+ }
}
if (failed) {
@@ -290,10 +375,11 @@
// Test new HashMap(0, -1.0F)
failed = true;
try {
- new HashMap(0, -1.0F);
+ new HashMap(CAPACITY_ZERO, LOAD_FACTOR_NEG_ONE);
} catch (Throwable ex) {
- if (ex instanceof IllegalArgumentException)
+ if (ex instanceof IllegalArgumentException) {
failed = false;
+ }
}
if (failed) {
@@ -301,7 +387,7 @@
}
// Test new HashMap(0,0F);
- hashMap = new HashMap(0, 0.1F);
+ hashMap = new HashMap(CAPACITY_ZERO, LOAD_FACTOR_ONE_TENTH);
assertNotNull(hashMap);
}
@@ -313,30 +399,23 @@
assertNotNull(srcMap);
checkEmptyHashMapAssumptions(srcMap);
- final Object KEY1 = new Integer(1);
- final Object VAL1 = new Integer(1);
- final Object KEY2 = new Integer(2);
- final Object VAL2 = new Integer(2);
- final Object KEY3 = new Integer(3);
- final Object VAL3 = new Integer(3);
+ srcMap.put(INTEGER_1, INTEGER_11);
+ srcMap.put(INTEGER_2, INTEGER_22);
+ srcMap.put(INTEGER_3, INTEGER_33);
- srcMap.put(KEY1, VAL1);
- srcMap.put(KEY2, VAL2);
- srcMap.put(KEY3, VAL3);
-
- HashMap hashMap = new HashMap(srcMap);
+ HashMap hashMap = cloneHashMap(srcMap);
assertFalse(hashMap.isEmpty());
- assertTrue(hashMap.size() == 3);
+ assertTrue(hashMap.size() == SIZE_THREE);
Collection valColl = hashMap.values();
- assertTrue(valColl.contains(VAL1));
- assertTrue(valColl.contains(VAL2));
- assertTrue(valColl.contains(VAL3));
+ assertTrue(valColl.contains(INTEGER_11));
+ assertTrue(valColl.contains(INTEGER_22));
+ assertTrue(valColl.contains(INTEGER_33));
Collection keyColl = hashMap.keySet();
- assertTrue(keyColl.contains(KEY1));
- assertTrue(keyColl.contains(KEY2));
- assertTrue(keyColl.contains(KEY3));
+ assertTrue(keyColl.contains(INTEGER_1));
+ assertTrue(keyColl.contains(INTEGER_2));
+ assertTrue(keyColl.contains(INTEGER_3));
}
/*
@@ -352,16 +431,38 @@
dstMap.putAll(srcMap);
assertTrue(dstMap.isEmpty());
- final String KEY = "key";
- final String VAL = "val";
- dstMap.put(KEY, VAL);
+ dstMap.put(KEY_KEY, VALUE_VAL);
assertFalse(dstMap.isEmpty());
- dstMap.remove(KEY);
+ dstMap.remove(KEY_KEY);
assertTrue(dstMap.isEmpty());
assertEquals(dstMap.size(), 0);
}
+ public void testKeysConflict() {
+ HashMap hashMap = new HashMap();
+
+ hashMap.put(STRING_ZERO_KEY,STRING_ZERO_VALUE);
+ hashMap.put(INTEGER_ZERO_KEY, INTEGER_ZERO_VALUE);
+ hashMap.put(ODD_ZERO_KEY, ODD_ZERO_VALUE);
+ assertEquals(hashMap.get(INTEGER_ZERO_KEY), INTEGER_ZERO_VALUE);
+ assertEquals(hashMap.get(ODD_ZERO_KEY), ODD_ZERO_VALUE);
+ assertEquals(hashMap.get(STRING_ZERO_KEY), STRING_ZERO_VALUE);
+ hashMap.remove(INTEGER_ZERO_KEY);
+ assertEquals(hashMap.get(ODD_ZERO_KEY), ODD_ZERO_VALUE);
+ assertEquals(hashMap.get(STRING_ZERO_KEY), STRING_ZERO_VALUE);
+ assertEquals(hashMap.get(INTEGER_ZERO_KEY), null);
+ hashMap.remove(ODD_ZERO_KEY);
+ assertEquals(hashMap.get(INTEGER_ZERO_KEY), null);
+ assertEquals(hashMap.get(ODD_ZERO_KEY), null);
+ assertEquals(hashMap.get(STRING_ZERO_KEY), STRING_ZERO_VALUE);
+ hashMap.remove(STRING_ZERO_KEY);
+ assertEquals(hashMap.get(INTEGER_ZERO_KEY), null);
+ assertEquals(hashMap.get(ODD_ZERO_KEY), null);
+ assertEquals(hashMap.get(STRING_ZERO_KEY), null);
+ assertEquals(hashMap.size(), 0);
+ }
+
/*
* Test method for 'java.util.HashMap.keySet()'
*/
@@ -374,14 +475,12 @@
assertTrue(keySet.isEmpty());
assertTrue(keySet.size() == 0);
- final String KEY = "testKeySet";
- final String VAL = KEY + " - value";
- hashMap.put(KEY, VAL);
+ hashMap.put(KEY_TEST_KEY_SET, VALUE_TEST_KEY_SET);
- assertTrue(keySet.size() == 1);
- assertTrue(keySet.contains(KEY));
- assertFalse(keySet.contains(VAL));
- assertFalse(keySet.contains(KEY.toUpperCase()));
+ assertTrue(keySet.size() == SIZE_ONE);
+ assertTrue(keySet.contains(KEY_TEST_KEY_SET));
+ assertFalse(keySet.contains(VALUE_TEST_KEY_SET));
+ assertFalse(keySet.contains(KEY_TEST_KEY_SET.toUpperCase()));
}
/*
@@ -391,35 +490,22 @@
HashMap hashMap = new HashMap();
checkEmptyHashMapAssumptions(hashMap);
- final String KEY = "testPut";
- final String VAL1 = KEY + " - value 1";
- final String VAL2 = KEY + " - value 2";
-
- assertNull(hashMap.put(KEY, VAL1));
- assertEquals(hashMap.put(KEY, VAL2), VAL1);
- assertNull(hashMap.put(null, VAL1));
- assertEquals(hashMap.put(null, VAL2), VAL1);
+ assertNull(hashMap.put(KEY_TEST_PUT, VALUE_TEST_PUT_1));
+ assertEquals(hashMap.put(KEY_TEST_PUT, VALUE_TEST_PUT_2), VALUE_TEST_PUT_1);
+ assertNull(hashMap.put(null, VALUE_TEST_PUT_1));
+ assertEquals(hashMap.put(null, VALUE_TEST_PUT_2), VALUE_TEST_PUT_1);
}
- /*
- * Test method for 'java.util.HashMap.putAll(Map)'
+ /**
+ * Test method for 'java.util.HashMap.putAll(Map)'.
*/
public void testPutAll() {
- final String KEY1 = "key1";
- final String VAL1 = "val1";
- final String KEY2 = "key2";
- final String VAL2 = "val2";
- final String KEY3 = "key3";
- final String VAL3 = "val3";
- final String KEY4 = "key4";
- final String VAL4 = "val4";
-
HashMap srcMap = new HashMap();
checkEmptyHashMapAssumptions(srcMap);
- srcMap.put(KEY1, VAL1);
- srcMap.put(KEY2, VAL2);
- srcMap.put(KEY3, VAL3);
+ srcMap.put(KEY_1, VALUE_1);
+ srcMap.put(KEY_2, VALUE_2);
+ srcMap.put(KEY_3, VALUE_3);
// Make sure that the data is copied correctly
HashMap dstMap = new HashMap();
@@ -427,134 +513,119 @@
dstMap.putAll(srcMap);
assertEquals(srcMap.size(), dstMap.size());
- assertTrue(dstMap.containsKey(KEY1));
- assertTrue(dstMap.containsValue(VAL1));
- assertFalse(dstMap.containsKey(KEY1.toUpperCase()));
- assertFalse(dstMap.containsValue(VAL1.toUpperCase()));
+ assertTrue(dstMap.containsKey(KEY_1));
+ assertTrue(dstMap.containsValue(VALUE_1));
+ assertFalse(dstMap.containsKey(KEY_1.toUpperCase()));
+ assertFalse(dstMap.containsValue(VALUE_1.toUpperCase()));
- assertTrue(dstMap.containsKey(KEY2));
- assertTrue(dstMap.containsValue(VAL2));
- assertFalse(dstMap.containsKey(KEY2.toUpperCase()));
- assertFalse(dstMap.containsValue(VAL2.toUpperCase()));
+ assertTrue(dstMap.containsKey(KEY_2));
+ assertTrue(dstMap.containsValue(VALUE_2));
+ assertFalse(dstMap.containsKey(KEY_2.toUpperCase()));
+ assertFalse(dstMap.containsValue(VALUE_2.toUpperCase()));
- assertTrue(dstMap.containsKey(KEY3));
- assertTrue(dstMap.containsValue(VAL3));
- assertFalse(dstMap.containsKey(KEY3.toUpperCase()));
- assertFalse(dstMap.containsValue(VAL3.toUpperCase()));
+ assertTrue(dstMap.containsKey(KEY_3));
+ assertTrue(dstMap.containsValue(VALUE_3));
+ assertFalse(dstMap.containsKey(KEY_3.toUpperCase()));
+ assertFalse(dstMap.containsValue(VALUE_3.toUpperCase()));
- // Check that an empty map does not blow away the contents of the dest map
+ // Check that an empty map does not blow away the contents of the destination map
HashMap emptyMap = new HashMap();
checkEmptyHashMapAssumptions(emptyMap);
dstMap.putAll(emptyMap);
assertTrue(dstMap.size() == srcMap.size());
- // Check that put all overwrite any existing mapping in the dst map
- srcMap.put(KEY1, VAL2);
- srcMap.put(KEY2, VAL3);
- srcMap.put(KEY3, VAL1);
+ // Check that put all overwrite any existing mapping in the destination map
+ srcMap.put(KEY_1, VALUE_2);
+ srcMap.put(KEY_2, VALUE_3);
+ srcMap.put(KEY_3, VALUE_1);
dstMap.putAll(srcMap);
assertEquals(dstMap.size(), srcMap.size());
- assertEquals(dstMap.get(KEY1), VAL2);
- assertEquals(dstMap.get(KEY2), VAL3);
- assertEquals(dstMap.get(KEY3), VAL1);
+ assertEquals(dstMap.get(KEY_1), VALUE_2);
+ assertEquals(dstMap.get(KEY_2), VALUE_3);
+ assertEquals(dstMap.get(KEY_3), VALUE_1);
- // Check that a putall does adds data but does not remove it
+ // Check that a putAll does adds data but does not remove it
- srcMap.put(KEY4, VAL4);
+ srcMap.put(KEY_4, VALUE_4);
dstMap.putAll(srcMap);
assertEquals(dstMap.size(), srcMap.size());
- assertTrue(dstMap.containsKey(KEY4));
- assertTrue(dstMap.containsValue(VAL4));
- assertEquals(dstMap.get(KEY1), VAL2);
- assertEquals(dstMap.get(KEY2), VAL3);
- assertEquals(dstMap.get(KEY3), VAL1);
- assertEquals(dstMap.get(KEY4), VAL4);
+ assertTrue(dstMap.containsKey(KEY_4));
+ assertTrue(dstMap.containsValue(VALUE_4));
+ assertEquals(dstMap.get(KEY_1), VALUE_2);
+ assertEquals(dstMap.get(KEY_2), VALUE_3);
+ assertEquals(dstMap.get(KEY_3), VALUE_1);
+ assertEquals(dstMap.get(KEY_4), VALUE_4);
dstMap.putAll(dstMap);
}
- /*
- * Test method for 'java.util.HashMap.remove(Object)'
+ /**
+ * Test method for 'java.util.HashMap.remove(Object)'.
*/
public void testRemove() {
- final String KEY = "testRemove";
- final String VAL = KEY + " - value";
-
HashMap hashMap = new HashMap();
checkEmptyHashMapAssumptions(hashMap);
assertNull(hashMap.remove(null));
- hashMap.put(null, VAL);
+ hashMap.put(null, VALUE_TEST_REMOVE);
assertNotNull(hashMap.remove(null));
- hashMap.put(KEY, VAL);
- assertEquals(hashMap.remove(KEY), VAL);
- assertNull(hashMap.remove(KEY));
+ hashMap.put(KEY_TEST_REMOVE, VALUE_TEST_REMOVE);
+ assertEquals(hashMap.remove(KEY_TEST_REMOVE), VALUE_TEST_REMOVE);
+ assertNull(hashMap.remove(KEY_TEST_REMOVE));
}
- /*
- * Test method for 'java.util.HashMap.size()'
+ /**
+ * Test method for 'java.util.HashMap.size()'.
*/
public void testSize() {
- final String KEY1 = "key1";
- final String VAL1 = KEY1 + " - value";
- final String KEY2 = "key2";
- final String VAL2 = KEY2 + " - value";
- final String KEY3 = "key3";
- final String VAL3 = KEY3 + " - value";
-
HashMap hashMap = new HashMap();
checkEmptyHashMapAssumptions(hashMap);
// Test size behavior on put
- assertEquals(hashMap.size(), 0);
- hashMap.put(KEY1, VAL1);
- assertEquals(hashMap.size(), 1);
- hashMap.put(KEY2, VAL2);
- assertEquals(hashMap.size(), 2);
- hashMap.put(KEY3, VAL3);
- assertEquals(hashMap.size(), 3);
+ assertEquals(hashMap.size(), SIZE_ZERO);
+ hashMap.put(KEY_1, VALUE_1);
+ assertEquals(hashMap.size(), SIZE_ONE);
+ hashMap.put(KEY_2, VALUE_2);
+ assertEquals(hashMap.size(), SIZE_TWO);
+ hashMap.put(KEY_3, VALUE_3);
+ assertEquals(hashMap.size(), SIZE_THREE);
// Test size behavior on remove
- hashMap.remove(KEY1);
- assertEquals(hashMap.size(), 2);
- hashMap.remove(KEY2);
- assertEquals(hashMap.size(), 1);
- hashMap.remove(KEY3);
- assertEquals(hashMap.size(), 0);
+ hashMap.remove(KEY_1);
+ assertEquals(hashMap.size(), SIZE_TWO);
+ hashMap.remove(KEY_2);
+ assertEquals(hashMap.size(), SIZE_ONE);
+ hashMap.remove(KEY_3);
+ assertEquals(hashMap.size(), SIZE_ZERO);
// Test size behavior on putAll
- hashMap.put(KEY1, VAL1);
- hashMap.put(KEY2, VAL2);
- hashMap.put(KEY3, VAL3);
-
- HashMap srcMap = new HashMap(hashMap);
+ hashMap.put(KEY_1, VALUE_1);
+ hashMap.put(KEY_2, VALUE_2);
+ hashMap.put(KEY_3, VALUE_3);
+ HashMap srcMap = cloneHashMap(hashMap);
hashMap.putAll(srcMap);
- assertEquals(hashMap.size(), 3);
+ assertEquals(hashMap.size(), SIZE_THREE);
// Test size behavior on clear
hashMap.clear();
- assertEquals(hashMap.size(), 0);
+ assertEquals(hashMap.size(), SIZE_ZERO);
}
- /*
- * Test method for 'java.util.AbstractMap.toString()'
+ /**
+ * Test method for 'java.util.AbstractMap.toString()'.
*/
public void testToString() {
HashMap hashMap = new HashMap();
checkEmptyHashMapAssumptions(hashMap);
-
- final String KEY = "key";
- final String VAL = "val";
- final String STR = "{" + KEY + "=" + VAL + "}";
- hashMap.put(KEY, VAL);
-
- assertTrue(STR.equals(hashMap.toString()));
+ hashMap.put(KEY_KEY, VALUE_VAL);
+ String entryString = makeEntryString(KEY_KEY, VALUE_VAL);
+ assertTrue(entryString.equals(hashMap.toString()));
}
/**
- * Test method for 'java.util.AbstractMap.values()'
+ * Test method for 'java.util.AbstractMap.values()'.
*/
public void testValues() {
HashMap hashMap = new HashMap();
@@ -562,17 +633,48 @@
assertNotNull(hashMap.values());
- final String KEY = "key";
- final String VAL = "val";
-
- hashMap.put(KEY, VAL);
+ hashMap.put(KEY_KEY, VALUE_VAL);
Collection valColl = hashMap.values();
assertNotNull(valColl);
- assertEquals(valColl.size(), 1);
+ assertEquals(valColl.size(), SIZE_ONE);
Iterator itVal = valColl.iterator();
String val = (String) itVal.next();
- assertEquals(val, VAL);
+ assertEquals(val, VALUE_VAL);
+ }
+
+ protected Map makeEmptyMap() {
+ return new HashMap();
+ }
+
+ /**
+ * This method exists because java 1.5 no longer has HashMap(HashMap), replacing
+ * it with HashMap(Map<? extends K, ? extends V> m). Nevertheless, we want
+ * to use it in web mode to test that web mode function.
+ *
+ * @param hashMap the HashMap to be copied
+ * @return the copy
+ */
+ private HashMap cloneHashMap(HashMap hashMap) {
+ if (GWT.isScript()) {
+ return new HashMap(hashMap);
+ } else {
+ HashMap m = new HashMap();
+ m.putAll(hashMap);
+ return m;
+ }
+ }
+
+ private Iterator iterateThrough(final HashMap expected) {
+ Iterator iter = expected.entrySet().iterator();
+ for (int i = 0; i < expected.size(); i++) {
+ iter.next();
+ }
+ return iter;
+ }
+
+ private String makeEntryString(final String key, final String value) {
+ return "{" + key + "=" + value + "}";
}
}
diff --git a/user/test/com/google/gwt/emultest/java/util/HashSetTest.java b/user/test/com/google/gwt/emultest/java/util/HashSetTest.java
index 91b757a..4e0e2d6 100644
--- a/user/test/com/google/gwt/emultest/java/util/HashSetTest.java
+++ b/user/test/com/google/gwt/emultest/java/util/HashSetTest.java
@@ -16,8 +16,13 @@
public void testAddingKeys(){
Map map = new HashMap();
Set keys = new HashSet(map.keySet());
- keys.add(new Object()); // Throws exception in IE6 (web-mode) but not GWT
-
+ keys.add(new Object()); // Throws exception in IE6 (web-mode) but not GWT
+ }
+
+ public void testAddWatch() {
+ HashSet s = new HashSet();
+ s.add("watch");
+ assertTrue(s.contains("watch"));
}
protected Set makeEmptySet() {