Adding LinkedHashMap and supporting tests and RPC serializers
Review by:jat (desk review)
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@2609 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/User.gwt.xml b/user/src/com/google/gwt/user/User.gwt.xml
index af4e794..eda5a3c 100644
--- a/user/src/com/google/gwt/user/User.gwt.xml
+++ b/user/src/com/google/gwt/user/User.gwt.xml
@@ -40,4 +40,8 @@
<inherits name="com.google.gwt.user.CaptionPanel" />
<inherits name="com.google.gwt.user.Window" />
<inherits name="com.google.gwt.user.Accessibility"/>
+
+ <super-source path="translatable"/>
+ <source path="client"/>
+
</module>
diff --git a/user/src/com/google/gwt/user/client/rpc/core/java/util/LinkedHashMap_CustomFieldSerializer.java b/user/src/com/google/gwt/user/client/rpc/core/java/util/LinkedHashMap_CustomFieldSerializer.java
new file mode 100644
index 0000000..820ffa7
--- /dev/null
+++ b/user/src/com/google/gwt/user/client/rpc/core/java/util/LinkedHashMap_CustomFieldSerializer.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2008 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.user.client.rpc.core.java.util;
+
+import com.google.gwt.user.client.rpc.SerializationException;
+import com.google.gwt.user.client.rpc.SerializationStreamReader;
+import com.google.gwt.user.client.rpc.SerializationStreamWriter;
+
+import java.lang.reflect.Field;
+import java.util.LinkedHashMap;
+import java.util.Set;
+import java.util.Map.Entry;
+
+/**
+ * Custom field serializer for {@link java.util.LinkedHashMap} for the server
+ * (uses reflection).
+ */
+public final class LinkedHashMap_CustomFieldSerializer {
+
+ public static void deserialize(SerializationStreamReader streamReader,
+ LinkedHashMap instance) throws SerializationException {
+ int size = streamReader.readInt();
+
+ for (int i = 0; i < size; ++i) {
+ Object key = streamReader.readObject();
+ Object value = streamReader.readObject();
+ instance.put(key, value);
+ }
+ }
+
+ public static LinkedHashMap instantiate(SerializationStreamReader streamReader)
+ throws SerializationException {
+ boolean accessOrder = streamReader.readBoolean();
+ return new LinkedHashMap(16, .75f, accessOrder);
+ }
+
+ public static void serialize(SerializationStreamWriter streamWriter,
+ LinkedHashMap instance) throws SerializationException {
+ streamWriter.writeBoolean(getAccessOrder(instance));
+ int size = instance.size();
+ streamWriter.writeInt(size);
+
+ for (Entry entry : (Set<Entry>) instance.entrySet()) {
+ streamWriter.writeObject(entry.getKey());
+ streamWriter.writeObject(entry.getValue());
+ }
+ }
+
+ private static boolean getAccessOrder(LinkedHashMap instance)
+ throws SerializationException {
+ Field accessOrderField;
+ try {
+ accessOrderField = LinkedHashMap.class.getDeclaredField("accessOrder");
+ accessOrderField.setAccessible(true);
+ return ((Boolean) accessOrderField.get(instance)).booleanValue();
+ } catch (SecurityException e) {
+ throw new SerializationException("Can't get accessOrder field", e);
+ } catch (NoSuchFieldException e) {
+ throw new SerializationException("Can't get accessOrder field", e);
+ } catch (IllegalArgumentException e) {
+ throw new SerializationException("Can't get accessOrder field", e);
+ } catch (IllegalAccessException e) {
+ throw new SerializationException("Can't get accessOrder field", e);
+ }
+ }
+
+}
diff --git a/user/super/com/google/gwt/emul/java/util/LinkedHashMap.java b/user/super/com/google/gwt/emul/java/util/LinkedHashMap.java
index ec4fef1..c1ff2a4 100644
--- a/user/super/com/google/gwt/emul/java/util/LinkedHashMap.java
+++ b/user/super/com/google/gwt/emul/java/util/LinkedHashMap.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 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
@@ -15,6 +15,8 @@
*/
package java.util;
+import java.io.Serializable;
+
/**
* Hash table implementation of the Map interface with predictable iteration
* order. <a
@@ -24,64 +26,277 @@
* @param <K> key type.
* @param <V> value type.
*/
-public class LinkedHashMap<K, V> extends HashMap<K, V> implements Map<K, V>,
- Cloneable {
+public class LinkedHashMap<K, V> extends HashMap<K, V> implements Map<K, V> {
+
+ /**
+ * The entry we use includes next/prev pointers for a doubly-linked circular
+ * list with a head node. This reduces the special cases we have to deal with
+ * in the list operations.
+ *
+ * Note that we duplicate the key from the underlying hashmap so we can find
+ * the eldest entry. The alternative would have been to modify HashMap so more
+ * of the code was directly usable here, but this would have added some
+ * overhead to HashMap, or to reimplement most of the HashMap code here with
+ * small modifications. Paying a small storage cost only if you use
+ * LinkedHashMap and minimizing code size seemed like a better tradeoff
+ */
+ private class ChainEntry extends MapEntryImpl<K, V> implements Serializable {
+ private transient ChainEntry next;
+ private transient ChainEntry prev;
+
+ public ChainEntry() {
+ this(null, null);
+ }
+
+ public ChainEntry(K key, V value) {
+ super(key, value);
+ next = prev = null;
+ }
+
+ /**
+ * Add this node after the specified node in the chain.
+ *
+ * @param node the node to insert after
+ */
+ public void addAfter(ChainEntry node) {
+ update(node, node.next);
+ }
+
+ /**
+ * Add this node before the specified node in the chain.
+ *
+ * @param node the node to insert before
+ */
+ public void addBefore(ChainEntry node) {
+ update(node.prev, node);
+ }
+
+ /**
+ * Remove this node from any list it may be a part of.
+ */
+ public void remove() {
+ next.prev = prev;
+ prev.next = next;
+ next = null;
+ prev = null;
+ }
+
+ private void update(ChainEntry prev, ChainEntry next) {
+ // This entry is not in the list.
+ assert (this.next == null) && (this.prev == null);
+
+ // Will not break the chain.
+ assert (prev != null && next != null);
+
+ // Update me.
+ this.prev = prev;
+ this.next = next;
+ next.prev = this;
+ prev.next = this;
+ }
+ }
+
+ private final class EntrySet extends AbstractSet<Map.Entry<K, V>> {
+
+ private final class EntryIterator implements Iterator<Entry<K, V>> {
+ // Current entry.
+ private ChainEntry current;
+
+ // Next entry. Used to allow removal of the current node.
+ private ChainEntry next;
+
+ public EntryIterator() {
+ current = head;
+ next = head.next;
+ }
+
+ public boolean hasNext() {
+ return next != head;
+ }
+
+ public java.util.Map.Entry<K, V> next() {
+ if (next == null) {
+ throw new NoSuchElementException();
+ }
+ current = next;
+ next = next.next;
+ return current;
+ }
+
+ public void remove() {
+ if (current == null || current == head) {
+ throw new IllegalStateException("No current entry");
+ }
+ current.remove();
+ map.remove(current.getKey());
+ current = null;
+ }
+ }
+
+ @Override
+ public void clear() {
+ LinkedHashMap.this.clear();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ if (!(o instanceof Map.Entry)) {
+ return false;
+ }
+ Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
+ Object key = entry.getKey();
+ if (LinkedHashMap.this.containsKey(key)) {
+ Object value = LinkedHashMap.this.get(key);
+ return Utility.equalsWithNullCheck(entry.getValue(), value);
+ }
+ return false;
+ }
+
+ @Override
+ public Iterator<Map.Entry<K, V>> iterator() {
+ return new EntryIterator();
+ }
+
+ @Override
+ public int size() {
+ return map.size();
+ }
+ }
+
+ // True if we should use the access order (ie, for LRU caches) instead of
+ // insertion order.
+ private transient boolean accessOrder;
+
+ /*
+ * The head of the LRU/insert order chain, which is a doubly-linked circular
+ * list.
+ *
+ * The most recently inserted/accessed node is at the end of the chain, ie.
+ * chain.prev.
+ */
+ private transient ChainEntry head;
+
+ /*
+ * The hashmap that keeps track of our entries and the chain. Note that we
+ * duplicate the key here to eliminate changes to HashMap and minimize the
+ * code here, at the expense of additional space.
+ */
+ private transient HashMap<K, ChainEntry> map;
+
+ {
+ // Head's value should never be accessed.
+ head = new ChainEntry();
+ head.prev = head;
+ head.next = head;
+ }
public LinkedHashMap() {
- this(11, 0.75f);
+ this(11, 0.75f, false);
}
- /**
- * @param ignored
- */
public LinkedHashMap(int ignored) {
- this(ignored, 0.75f);
+ this(ignored, 0.75f, false);
}
- /**
- * @param ignored
- * @param alsoIgnored
- */
public LinkedHashMap(int ignored, float alsoIgnored) {
- super(ignored, alsoIgnored);
- // TODO(jat): implement
- throw new UnsupportedOperationException("LinkedHashMap not supported");
+ this(ignored, alsoIgnored, false);
}
- /**
- * @param toBeCopied
- */
+ public LinkedHashMap(int ignored, float alsoIgnored, boolean accessOrder) {
+ super();
+ this.accessOrder = accessOrder;
+ this.map = new HashMap<K, ChainEntry>(ignored, alsoIgnored);
+ }
+
public LinkedHashMap(Map<? extends K, ? extends V> toBeCopied) {
- this();
+ this(toBeCopied.size());
putAll(toBeCopied);
}
@Override
public void clear() {
- // TODO(jat): implement
+ map.clear();
+ head.prev = head;
+ head.next = head;
}
@Override
- public Object clone() {
- // TODO(jat): implement
+ public boolean containsKey(Object key) {
+ return map.containsKey(key);
+ }
+
+ @Override
+ public boolean containsValue(Object value) {
+ ChainEntry node = head.next;
+ while (node != head) {
+ if (Utility.equalsWithNullCheck(node.getValue(), value)) {
+ return true;
+ }
+ node = node.next;
+ }
+ return false;
+ }
+
+ @Override
+ public Set<Map.Entry<K, V>> entrySet() {
+ return new EntrySet();
+ }
+
+ @Override
+ public V get(Object key) {
+ ChainEntry entry = map.get(key);
+ if (entry != null) {
+ if (accessOrder) {
+ // Move to the tail of the chain on access if requested.
+ entry.remove();
+ entry.addBefore(head);
+ }
+ return entry.getValue();
+ }
return null;
}
@Override
public V put(K key, V value) {
- // TODO(jat): implement
- return null;
+ ChainEntry old = map.get(key);
+ if (old == null) {
+ ChainEntry newEntry = new ChainEntry(key, value);
+ map.put(key, newEntry);
+ newEntry.addBefore(head);
+ ChainEntry eldest = head.next;
+ if (removeEldestEntry(eldest)) {
+ eldest.remove();
+ map.remove(eldest.getKey());
+ }
+ return null;
+ } else {
+ V oldValue = old.getValue();
+ old.setValue(value);
+ // If orders by access, move to end of execution block.
+ if (accessOrder) {
+ old.remove();
+ old.addBefore(head);
+ }
+ return oldValue;
+ }
}
@Override
public V remove(Object key) {
- // TODO(jat): implement
+ ChainEntry entry = map.remove(key);
+ if (entry != null) {
+ entry.remove();
+ return entry.getValue();
+ }
return null;
}
- protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
- // TODO(jat): implement
- return false;
+ @Override
+ public int size() {
+ return map.size();
}
+ protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
+ return false;
+ }
}
diff --git a/user/super/com/google/gwt/user/translatable/com/google/gwt/user/client/rpc/core/java/util/LinkedHashMap_CustomFieldSerializer.java b/user/super/com/google/gwt/user/translatable/com/google/gwt/user/client/rpc/core/java/util/LinkedHashMap_CustomFieldSerializer.java
new file mode 100644
index 0000000..a930bda
--- /dev/null
+++ b/user/super/com/google/gwt/user/translatable/com/google/gwt/user/client/rpc/core/java/util/LinkedHashMap_CustomFieldSerializer.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2008 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.user.client.rpc.core.java.util;
+
+import com.google.gwt.user.client.rpc.SerializationException;
+import com.google.gwt.user.client.rpc.SerializationStreamReader;
+import com.google.gwt.user.client.rpc.SerializationStreamWriter;
+
+import java.util.LinkedHashMap;
+import java.util.Set;
+import java.util.Map.Entry;
+
+/**
+ * Custom field serializer for {@link java.util.LinkedHashMap}, which is the
+ * same as {@link java.util.HashMap}.
+ */
+public final class LinkedHashMap_CustomFieldSerializer {
+
+ public static void deserialize(SerializationStreamReader streamReader,
+ LinkedHashMap instance) throws SerializationException {
+ int size = streamReader.readInt();
+
+ for (int i = 0; i < size; ++i) {
+ Object key = streamReader.readObject();
+ Object value = streamReader.readObject();
+ instance.put(key, value);
+ }
+ }
+
+ public static LinkedHashMap instantiate(SerializationStreamReader streamReader)
+ throws SerializationException {
+ boolean accessOrder = streamReader.readBoolean();
+ return new LinkedHashMap(16, .75f, accessOrder);
+ }
+
+ public static void serialize(SerializationStreamWriter streamWriter,
+ LinkedHashMap instance) throws SerializationException {
+ streamWriter.writeBoolean(getAccessOrder(instance));
+ int size = instance.size();
+ streamWriter.writeInt(size);
+
+ for (Entry entry : (Set<Entry>) instance.entrySet()) {
+ streamWriter.writeObject(entry.getKey());
+ streamWriter.writeObject(entry.getValue());
+ }
+ }
+
+ private static native boolean getAccessOrder(LinkedHashMap instance) /*-{
+ return instance.@java.util.LinkedHashMap::accessOrder;
+ }-*/;
+}
diff --git a/user/test/com/google/gwt/emultest/java/util/CollectionsTest.java b/user/test/com/google/gwt/emultest/java/util/CollectionsTest.java
index 51898e7..8ae4f67 100644
--- a/user/test/com/google/gwt/emultest/java/util/CollectionsTest.java
+++ b/user/test/com/google/gwt/emultest/java/util/CollectionsTest.java
@@ -19,6 +19,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
+import java.util.LinkedHashMap;
import java.util.List;
/**
@@ -26,6 +27,10 @@
*/
public class CollectionsTest extends EmulTestBase {
+ LinkedHashMap dummy() {
+ return new LinkedHashMap();
+ }
+
public static List createSortedList() {
ArrayList l = new ArrayList();
l.add("a");
@@ -46,13 +51,10 @@
/**
* Test Collections.binarySearch(List, Object).
- *
- * Verify the following cases:
- * empty List
- * odd numbers of elements
- * even numbers of elements
- * not found value larger than all elements
- * not found value smaller than all elements
+ *
+ * Verify the following cases: empty List odd numbers of elements even numbers
+ * of elements not found value larger than all elements not found value
+ * smaller than all elements
*/
public void testBinarySearchObject() {
List a1 = new ArrayList();
@@ -63,7 +65,7 @@
assertEquals(-2, ret);
ret = Collections.binarySearch(a2, "y");
assertEquals(2, ret);
- List a3 = new ArrayList(Arrays.asList(new String[]{"b", "c", "x", "y"}));
+ List a3 = new ArrayList(Arrays.asList(new String[] {"b", "c", "x", "y"}));
ret = Collections.binarySearch(a3, "z");
assertEquals(-5, ret);
ret = Collections.binarySearch(a3, "a");
@@ -74,14 +76,10 @@
/**
* Test Collections.binarySearch(List, Object, Comparator).
- *
- * Verify the following cases:
- * empty List
- * odd numbers of elements
- * even numbers of elements
- * not found value larger than all elements
- * not found value smaller than all elements
- * null Comparator uses natural ordering
+ *
+ * Verify the following cases: empty List odd numbers of elements even numbers
+ * of elements not found value larger than all elements not found value
+ * smaller than all elements null Comparator uses natural ordering
*/
public void testBinarySearchObjectComparator() {
Comparator inverseSort = new Comparator() {
@@ -92,12 +90,12 @@
List a1 = new ArrayList();
int ret = Collections.binarySearch(a1, "", inverseSort);
assertEquals(-1, ret);
- List a2 = new ArrayList(Arrays.asList(new String[]{"y", "g", "a"}));
+ List a2 = new ArrayList(Arrays.asList(new String[] {"y", "g", "a"}));
ret = Collections.binarySearch(a2, "c", inverseSort);
assertEquals(-3, ret);
ret = Collections.binarySearch(a2, "a", inverseSort);
assertEquals(2, ret);
- List a3 = new ArrayList(Arrays.asList(new String[]{"y", "x", "c", "b"}));
+ List a3 = new ArrayList(Arrays.asList(new String[] {"y", "x", "c", "b"}));
ret = Collections.binarySearch(a3, "a", inverseSort);
assertEquals(-5, ret);
ret = Collections.binarySearch(a3, "z", inverseSort);
@@ -105,8 +103,8 @@
ret = Collections.binarySearch(a3, "y", inverseSort);
assertEquals(0, ret);
- List a4 = new ArrayList(Arrays.asList(
- new String[]{"a", "b", "c", "d", "e"}));
+ List a4 = new ArrayList(
+ Arrays.asList(new String[] {"a", "b", "c", "d", "e"}));
ret = Collections.binarySearch(a4, "d", null); // should not NPE
assertEquals(3, ret);
}
@@ -154,7 +152,7 @@
Object[] expected = {"c", "b", "a"};
assertEquals(expected, a);
}
-
+
public void testToArray() {
List<Integer> testList = createRandomList();
Integer[] testArray = new Integer[testList.size()];
diff --git a/user/test/com/google/gwt/emultest/java/util/LinkedHashMapTest.java b/user/test/com/google/gwt/emultest/java/util/LinkedHashMapTest.java
new file mode 100644
index 0000000..c493ca1
--- /dev/null
+++ b/user/test/com/google/gwt/emultest/java/util/LinkedHashMapTest.java
@@ -0,0 +1,780 @@
+/*
+ * 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.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+import java.util.LinkedHashMap;
+
+/**
+ * Tests <code>LinkedHashMap</code>.
+ */
+public class LinkedHashMapTest 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() {
+ @Override
+ 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 LinkedHashMap.
+ *
+ * @param hashMap
+ */
+ private static void checkEmptyLinkedHashMapAssumptions(LinkedHashMap hashMap) {
+ assertNotNull(hashMap);
+ assertTrue(hashMap.isEmpty());
+
+ assertNotNull(hashMap.values());
+ assertTrue(hashMap.values().isEmpty());
+ assertTrue(hashMap.values().size() == 0);
+
+ assertNotNull(hashMap.keySet());
+ assertTrue(hashMap.keySet().isEmpty());
+ assertTrue(hashMap.keySet().size() == 0);
+
+ assertNotNull(hashMap.entrySet());
+ assertTrue(hashMap.entrySet().isEmpty());
+ assertTrue(hashMap.entrySet().size() == 0);
+
+ assertNotNull(hashMap.entrySet().iterator());
+ assertFalse(hashMap.entrySet().iterator().hasNext());
+ }
+
+ @Override
+ public String getModuleName() {
+ return "com.google.gwt.emultest.EmulSuite";
+ }
+
+ // should be a method-level class, however to avoid serialization warning made
+ // static instead.
+ static class TestRemoveEldestMap extends LinkedHashMap {
+
+ public boolean removeEldest;
+ public String expectedKey;
+
+ public TestRemoveEldestMap() {
+ this(false);
+ }
+
+ public TestRemoveEldestMap(boolean accessOrder) {
+ super(1, .5f, accessOrder);
+ }
+
+ @Override
+ public boolean removeEldestEntry(Map.Entry entry) {
+ if (removeEldest) {
+ assertEquals(expectedKey, entry.getKey());
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ public void testRemoveEldest() {
+ TestRemoveEldestMap m = new TestRemoveEldestMap(false);
+ m.put("A", "A");
+ m.put("B", "B");
+ m.put("C", "C");
+ m.put("D", "D");
+ m.get("B");
+ m.get("D");
+ m.removeEldest = true;
+ m.expectedKey = "A";
+ m.put("E", "E");
+ m.put("B", "New-B");
+ Iterator<Map.Entry> entries = m.entrySet().iterator();
+ Map.Entry first = entries.next();
+ assertEquals("B", first.getKey());
+ assertEquals("New-B", first.getValue());
+ assertEquals(4, m.size());
+ }
+
+ public void testRemoveEldestMapLRU() {
+ TestRemoveEldestMap m;
+ Iterator<Map.Entry> entries;
+ Map.Entry first;
+ m = new TestRemoveEldestMap(true);
+ m.put("A", "A");
+ m.put("B", "B");
+ m.put("C", "C");
+ m.put("D", "D");
+ m.get("A");
+ m.get("D");
+ m.removeEldest = true;
+ m.expectedKey = "B";
+ m.put("E", "E");
+
+ m.put("C", "New-C");
+ entries = m.entrySet().iterator();
+ first = entries.next();
+ assertEquals("A", first.getKey());
+ assertEquals("D", entries.next().getKey());
+ assertEquals("E", entries.next().getKey());
+ assertEquals("New-C", entries.next().getValue());
+ }
+
+ public void testAddWatch() {
+ LinkedHashMap<String, String> m = new LinkedHashMap<String, String>();
+ m.put("watch", "watch");
+ assertEquals(m.get("watch"), "watch");
+ }
+
+ public void testLRU() {
+ LinkedHashMap<String, String> m = new LinkedHashMap<String, String>(10,
+ .5f, true);
+ m.put("A", "A");
+ m.put("B", "B");
+ m.put("C", "C");
+ m.put("D", "D");
+ Iterator<Entry<String, String>> entry = m.entrySet().iterator();
+ assertEquals("A", entry.next().getValue());
+ assertEquals("B", entry.next().getValue());
+ assertEquals("C", entry.next().getValue());
+ assertEquals("D", entry.next().getValue());
+ m.get("B");
+ m.get("D");
+ entry = m.entrySet().iterator();
+ assertEquals("A", entry.next().getValue());
+ assertEquals("C", entry.next().getValue());
+ assertEquals("B", entry.next().getValue());
+ assertEquals("D", entry.next().getValue());
+ }
+
+ public void testAddEqualKeys() {
+ final LinkedHashMap<Number, Object> expected = new LinkedHashMap<Number, Object>();
+ 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.LinkedHashMap.clear()'
+ */
+ public void testClear() {
+ LinkedHashMap<String, String> hashMap = new LinkedHashMap<String, String>();
+ checkEmptyLinkedHashMapAssumptions(hashMap);
+
+ hashMap.put("Hello", "Bye");
+ assertFalse(hashMap.isEmpty());
+ assertTrue(hashMap.size() == SIZE_ONE);
+
+ hashMap.clear();
+ assertTrue(hashMap.isEmpty());
+ assertTrue(hashMap.size() == 0);
+ }
+
+ /*
+ * Test method for 'java.util.LinkedHashMap.clone()'
+ */
+ // public void donttestClone() {
+ // LinkedHashMap srcMap = new LinkedHashMap();
+ // checkEmptyLinkedHashMapAssumptions(srcMap);
+ //
+ // // Check empty clone behavior
+ // LinkedHashMap dstMap = (LinkedHashMap) srcMap.clone();
+ // assertNotNull(dstMap);
+ // assertEquals(dstMap.size(), srcMap.size());
+ // // assertTrue(dstMap.values().toArray().equals(srcMap.values().toArray()));
+ // assertTrue(dstMap.keySet().equals(srcMap.keySet()));
+ // assertTrue(dstMap.entrySet().equals(srcMap.entrySet()));
+ //
+ // // Check non-empty clone behavior
+ // srcMap.put(KEY_1, VALUE_1);
+ // srcMap.put(KEY_2, VALUE_2);
+ // srcMap.put(KEY_3, VALUE_3);
+ // dstMap = (LinkedHashMap) srcMap.clone();
+ // assertNotNull(dstMap);
+ // assertEquals(dstMap.size(), srcMap.size());
+ //
+ // assertTrue(dstMap.keySet().equals(srcMap.keySet()));
+ //
+ // assertTrue(dstMap.entrySet().equals(srcMap.entrySet()));
+ // }
+ /*
+ * Test method for 'java.util.LinkedHashMap.containsKey(Object)'
+ */
+ public void testContainsKey() {
+ LinkedHashMap hashMap = new LinkedHashMap();
+ checkEmptyLinkedHashMapAssumptions(hashMap);
+
+ 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, VALUE_TEST_CONTAINS_KEY);
+ assertTrue(hashMap.containsKey(null));
+ }
+
+ /*
+ * Test method for 'java.util.LinkedHashMap.containsValue(Object)'
+ */
+ public void testContainsValue() {
+ LinkedHashMap hashMap = new LinkedHashMap();
+ checkEmptyLinkedHashMapAssumptions(hashMap);
+
+ 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_TEST_CONTAINS_VALUE, null);
+ assertTrue(hashMap.containsValue(null));
+ }
+
+ /*
+ * Test method for 'java.util.LinkedHashMap.entrySet()'
+ */
+ public void testEntrySet() {
+ LinkedHashMap hashMap = new LinkedHashMap();
+ checkEmptyLinkedHashMapAssumptions(hashMap);
+
+ Set entrySet = hashMap.entrySet();
+ assertNotNull(entrySet);
+
+ // Check that the entry set looks right
+ hashMap.put(KEY_TEST_ENTRY_SET, VALUE_TEST_ENTRY_SET_1);
+ entrySet = hashMap.entrySet();
+ assertEquals(entrySet.size(), SIZE_ONE);
+ Iterator itSet = entrySet.iterator();
+ Map.Entry entry = (Map.Entry) itSet.next();
+ 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_TEST_ENTRY_SET, VALUE_TEST_ENTRY_SET_2);
+ entrySet = hashMap.entrySet();
+ assertEquals(entrySet.size(), SIZE_ONE);
+ itSet = entrySet.iterator();
+ entry = (Map.Entry) itSet.next();
+ 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_TEST_ENTRY_SET);
+ checkEmptyLinkedHashMapAssumptions(hashMap);
+ }
+
+ /*
+ * Used to test the entrySet remove method.
+ */
+ public void testEntrySetRemove() {
+ LinkedHashMap<String, String> hashMap = new LinkedHashMap<String, String>();
+ hashMap.put("A", "B");
+ LinkedHashMap<String, String> dummy = new LinkedHashMap<String, String>();
+ 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)'
+ */
+ // public void testEquals() {
+ // LinkedHashMap hashMap = new LinkedHashMap();
+ // checkEmptyLinkedHashMapAssumptions(hashMap);
+ //
+ // hashMap.put(KEY_KEY, VALUE_VAL);
+ //
+ // LinkedHashMap copyMap = (LinkedHashMap) hashMap.clone();
+ //
+ // assertTrue(hashMap.equals(copyMap));
+ // hashMap.put(VALUE_VAL, KEY_KEY);
+ // assertFalse(hashMap.equals(copyMap));
+ // }
+ /*
+ * Test method for 'java.lang.Object.finalize()'.
+ */
+ public void testFinalize() {
+ // no tests for finalize
+ }
+
+ /*
+ * Test method for 'java.util.LinkedHashMap.get(Object)'.
+ */
+ public void testGet() {
+ LinkedHashMap hashMap = new LinkedHashMap();
+ checkEmptyLinkedHashMapAssumptions(hashMap);
+
+ 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, VALUE_TEST_GET);
+ assertNotNull(hashMap.get(null));
+
+ hashMap.put(null, null);
+ assertNull(hashMap.get(null));
+ }
+
+ /*
+ * Test method for 'java.util.AbstractMap.hashCode()'.
+ */
+ public void testHashCode() {
+ LinkedHashMap hashMap = new LinkedHashMap();
+ checkEmptyLinkedHashMapAssumptions(hashMap);
+
+ // Check that hashCode changes
+ int hashCode1 = hashMap.hashCode();
+ hashMap.put(KEY_KEY, VALUE_VAL);
+ int hashCode2 = hashMap.hashCode();
+
+ assertTrue(hashCode1 != hashCode2);
+ }
+
+ /*
+ * Test method for 'java.util.LinkedHashMap.LinkedHashMap()'.
+ */
+ public void testLinkedHashMap() {
+ LinkedHashMap hashMap = new LinkedHashMap();
+ checkEmptyLinkedHashMapAssumptions(hashMap);
+ }
+
+ /*
+ * Test method for 'java.util.LinkedHashMap.LinkedHashMap(int)'
+ */
+ public void testLinkedHashMapInt() {
+ LinkedHashMap hashMap = new LinkedHashMap(CAPACITY_16);
+ checkEmptyLinkedHashMapAssumptions(hashMap);
+
+ // TODO(mmendez): how do we verify capacity?
+ boolean failed = true;
+ try {
+ new LinkedHashMap(-SIZE_ONE);
+ } catch (Throwable ex) {
+ if (ex instanceof IllegalArgumentException) {
+ failed = false;
+ }
+ }
+
+ if (failed) {
+ fail("Failure testing new LinkedHashMap(-1)");
+ }
+
+ LinkedHashMap zeroSizedLinkedHashMap = new LinkedHashMap(0);
+ assertNotNull(zeroSizedLinkedHashMap);
+ }
+
+ /*
+ * Test method for 'java.util.LinkedHashMap.LinkedHashMap(int, float)'
+ */
+ public void testLinkedHashMapIntFloat() {
+
+ LinkedHashMap hashMap = new LinkedHashMap(CAPACITY_16, LOAD_FACTOR_ONE_HALF);
+ checkEmptyLinkedHashMapAssumptions(hashMap);
+
+ // TODO(mmendez): how do we verify capacity and load factor?
+
+ // Test new LinkedHashMap(-1, 0.0F)
+ boolean failed = true;
+ try {
+ new LinkedHashMap(CAPACITY_NEG_ONE_HALF, LOAD_FACTOR_ZERO);
+ } catch (Throwable ex) {
+ if (ex instanceof IllegalArgumentException) {
+ failed = false;
+ }
+ }
+
+ if (failed) {
+ fail("Failure testing new LinkedHashMap(-1, 0.0F)");
+ }
+
+ // Test new LinkedHashMap(0, -1.0F)
+ failed = true;
+ try {
+ new LinkedHashMap(CAPACITY_ZERO, LOAD_FACTOR_NEG_ONE);
+ } catch (Throwable ex) {
+ if (ex instanceof IllegalArgumentException) {
+ failed = false;
+ }
+ }
+
+ if (failed) {
+ fail("Failure testing new LinkedHashMap(0, -1.0F)");
+ }
+
+ // Test new LinkedHashMap(0,0F);
+ hashMap = new LinkedHashMap(CAPACITY_ZERO, LOAD_FACTOR_ONE_TENTH);
+ assertNotNull(hashMap);
+ }
+
+ /*
+ * Test method for 'java.util.LinkedHashMap.LinkedHashMap(Map)'
+ */
+ public void testLinkedHashMapMap() {
+ LinkedHashMap srcMap = new LinkedHashMap();
+ assertNotNull(srcMap);
+ checkEmptyLinkedHashMapAssumptions(srcMap);
+
+ srcMap.put(INTEGER_1, INTEGER_11);
+ srcMap.put(INTEGER_2, INTEGER_22);
+ srcMap.put(INTEGER_3, INTEGER_33);
+
+ LinkedHashMap hashMap = cloneLinkedHashMap(srcMap);
+ assertFalse(hashMap.isEmpty());
+ assertTrue(hashMap.size() == SIZE_THREE);
+
+ Collection valColl = hashMap.values();
+ assertTrue(valColl.contains(INTEGER_11));
+ assertTrue(valColl.contains(INTEGER_22));
+ assertTrue(valColl.contains(INTEGER_33));
+
+ Collection keyColl = hashMap.keySet();
+ assertTrue(keyColl.contains(INTEGER_1));
+ assertTrue(keyColl.contains(INTEGER_2));
+ assertTrue(keyColl.contains(INTEGER_3));
+ }
+
+ /*
+ * Test method for 'java.util.AbstractMap.isEmpty()'
+ */
+ public void testIsEmpty() {
+ LinkedHashMap<String, String> srcMap = new LinkedHashMap<String, String>();
+ checkEmptyLinkedHashMapAssumptions(srcMap);
+
+ LinkedHashMap<String, String> dstMap = new LinkedHashMap<String, String>();
+ checkEmptyLinkedHashMapAssumptions(dstMap);
+
+ dstMap.putAll(srcMap);
+ assertTrue(dstMap.isEmpty());
+
+ dstMap.put(KEY_KEY, VALUE_VAL);
+ assertFalse(dstMap.isEmpty());
+
+ dstMap.remove(KEY_KEY);
+ assertTrue(dstMap.isEmpty());
+ assertEquals(dstMap.size(), 0);
+ }
+
+ public void testKeysConflict() {
+ LinkedHashMap<Object, String> hashMap = new LinkedHashMap<Object, String>();
+
+ 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.LinkedHashMap.keySet()'
+ */
+ public void testKeySet() {
+ LinkedHashMap<String, String> hashMap = new LinkedHashMap<String, String>();
+ checkEmptyLinkedHashMapAssumptions(hashMap);
+
+ Set keySet = hashMap.keySet();
+ System.err.println("keySet:" + keySet);
+ assertNotNull(keySet);
+ assertTrue(keySet.isEmpty());
+ assertTrue(keySet.size() == 0);
+
+ hashMap.put(KEY_TEST_KEY_SET, VALUE_TEST_KEY_SET);
+ assertEquals(SIZE_ONE, keySet.size());
+ assertTrue(keySet.contains(KEY_TEST_KEY_SET));
+ assertFalse(keySet.contains(VALUE_TEST_KEY_SET));
+ assertFalse(keySet.contains(KEY_TEST_KEY_SET.toUpperCase()));
+ }
+
+ /*
+ * Test method for 'java.util.LinkedHashMap.put(Object, Object)'
+ */
+ public void testPut() {
+ LinkedHashMap<String, String> hashMap = new LinkedHashMap<String, String>();
+ checkEmptyLinkedHashMapAssumptions(hashMap);
+
+ 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.LinkedHashMap.putAll(Map)'.
+ */
+ public void testPutAll() {
+ LinkedHashMap<String, String> srcMap = new LinkedHashMap<String, String>();
+ checkEmptyLinkedHashMapAssumptions(srcMap);
+
+ 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
+ LinkedHashMap<String, String> dstMap = new LinkedHashMap<String, String>();
+ checkEmptyLinkedHashMapAssumptions(dstMap);
+
+ dstMap.putAll(srcMap);
+ assertEquals(srcMap.size(), dstMap.size());
+ 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(KEY_2));
+ assertTrue(dstMap.containsValue(VALUE_2));
+ assertFalse(dstMap.containsKey(KEY_2.toUpperCase()));
+ assertFalse(dstMap.containsValue(VALUE_2.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
+ // destination map
+ LinkedHashMap<String, String> emptyMap = new LinkedHashMap<String, String>();
+ checkEmptyLinkedHashMapAssumptions(emptyMap);
+ dstMap.putAll(emptyMap);
+ assertTrue(dstMap.size() == srcMap.size());
+
+ // 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(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
+
+ srcMap.put(KEY_4, VALUE_4);
+ dstMap.putAll(srcMap);
+ assertEquals(dstMap.size(), srcMap.size());
+ 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.LinkedHashMap.remove(Object)'.
+ */
+ public void testRemove() {
+ LinkedHashMap<String, String> hashMap = new LinkedHashMap<String, String>();
+ checkEmptyLinkedHashMapAssumptions(hashMap);
+
+ assertNull(hashMap.remove(null));
+ hashMap.put(null, VALUE_TEST_REMOVE);
+ assertNotNull(hashMap.remove(null));
+
+ 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.LinkedHashMap.size()'.
+ */
+ public void testSize() {
+ LinkedHashMap<String, String> hashMap = new LinkedHashMap<String, String>();
+ checkEmptyLinkedHashMapAssumptions(hashMap);
+
+ // Test size behavior on put
+ 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(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(KEY_1, VALUE_1);
+ hashMap.put(KEY_2, VALUE_2);
+ hashMap.put(KEY_3, VALUE_3);
+ LinkedHashMap srcMap = cloneLinkedHashMap(hashMap);
+ hashMap.putAll(srcMap);
+ assertEquals(hashMap.size(), SIZE_THREE);
+
+ // Test size behavior on clear
+ hashMap.clear();
+ assertEquals(hashMap.size(), SIZE_ZERO);
+ }
+
+ /**
+ * Test method for 'java.util.AbstractMap.toString()'.
+ */
+ public void testToString() {
+ LinkedHashMap<String, String> hashMap = new LinkedHashMap<String, String>();
+ checkEmptyLinkedHashMapAssumptions(hashMap);
+ 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()'.
+ */
+ public void testValues() {
+ LinkedHashMap<String, String> hashMap = new LinkedHashMap<String, String>();
+ checkEmptyLinkedHashMapAssumptions(hashMap);
+
+ assertNotNull(hashMap.values());
+
+ hashMap.put(KEY_KEY, VALUE_VAL);
+
+ Collection<String> valColl = hashMap.values();
+ assertNotNull(valColl);
+ assertEquals(valColl.size(), SIZE_ONE);
+
+ Iterator<String> itVal = valColl.iterator();
+ String val = itVal.next();
+ assertEquals(val, VALUE_VAL);
+ }
+
+ @Override
+ protected Map makeEmptyMap() {
+ return new LinkedHashMap();
+ }
+
+ /**
+ * This method exists because java 1.5 no longer has
+ * LinkedHashMap(LinkedHashMap), replacing it with LinkedHashMap(Map<?
+ * extends K, ? extends V> m). Nevertheless, we want to use it in web mode to
+ * test that web mode function.
+ *
+ * @param hashMap the LinkedHashMap to be copied
+ * @return the copy
+ */
+ private LinkedHashMap cloneLinkedHashMap(LinkedHashMap hashMap) {
+ if (GWT.isScript()) {
+ return new LinkedHashMap(hashMap);
+ } else {
+ LinkedHashMap m = new LinkedHashMap();
+ m.putAll(hashMap);
+ return m;
+ }
+ }
+
+ private Iterator<Map.Entry<Number, Object>> iterateThrough(
+ final LinkedHashMap<Number, Object> expected) {
+ Iterator<Map.Entry<Number, Object>> 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/user/client/rpc/CollectionsTest.java b/user/test/com/google/gwt/user/client/rpc/CollectionsTest.java
index 214dea4..b35e439 100644
--- a/user/test/com/google/gwt/user/client/rpc/CollectionsTest.java
+++ b/user/test/com/google/gwt/user/client/rpc/CollectionsTest.java
@@ -24,6 +24,7 @@
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Vector;
@@ -264,6 +265,51 @@
});
}
+ public void testLinkedHashMap() {
+ delayTestFinish(TEST_DELAY);
+ CollectionsTestServiceAsync service = getServiceAsync();
+
+ final LinkedHashMap<String, IsSerializable> expected = TestSetFactory.createLinkedHashMap();
+
+ service.echo(expected,
+ new AsyncCallback<LinkedHashMap<String, IsSerializable>>() {
+ public void onFailure(Throwable caught) {
+ TestSetValidator.rethrowException(caught);
+ }
+
+ public void onSuccess(LinkedHashMap<String, IsSerializable> result) {
+ assertNotNull(result);
+ expected.get("SerializableSet");
+ result.get("SerializableSet");
+ assertTrue(TestSetValidator.isValid(expected,
+ (LinkedHashMap) result));
+ finishTest();
+ }
+ });
+ }
+
+ public void testLinkedHashMapLRU() {
+ delayTestFinish(TEST_DELAY);
+ CollectionsTestServiceAsync service = getServiceAsync();
+
+ final LinkedHashMap<String, IsSerializable> expected = TestSetFactory.createLRULinkedHashMap();
+
+ service.echo(expected,
+ new AsyncCallback<LinkedHashMap<String, IsSerializable>>() {
+ public void onFailure(Throwable caught) {
+ TestSetValidator.rethrowException(caught);
+ }
+
+ public void onSuccess(LinkedHashMap actual) {
+ assertNotNull(actual);
+ expected.get("SerializableSet");
+ actual.get("SerializableSet");
+ assertTrue(TestSetValidator.isValid(expected, actual));
+ finishTest();
+ }
+ });
+ }
+
public void testLongArray() {
delayTestFinish(TEST_DELAY);
diff --git a/user/test/com/google/gwt/user/client/rpc/CollectionsTestService.java b/user/test/com/google/gwt/user/client/rpc/CollectionsTestService.java
index 114f2c8..84c6330 100644
--- a/user/test/com/google/gwt/user/client/rpc/CollectionsTestService.java
+++ b/user/test/com/google/gwt/user/client/rpc/CollectionsTestService.java
@@ -21,6 +21,7 @@
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Vector;
@@ -72,6 +73,10 @@
HashMap<String, IsSerializable> echo(HashMap<String, IsSerializable> value)
throws CollectionsTestServiceException;
+ LinkedHashMap<String, IsSerializable> echo(
+ LinkedHashMap<String, IsSerializable> value)
+ throws CollectionsTestServiceException;
+
HashSet<IsSerializable> echo(HashSet<IsSerializable> value)
throws CollectionsTestServiceException;
diff --git a/user/test/com/google/gwt/user/client/rpc/CollectionsTestServiceAsync.java b/user/test/com/google/gwt/user/client/rpc/CollectionsTestServiceAsync.java
index 1a4d331..4c9187e 100644
--- a/user/test/com/google/gwt/user/client/rpc/CollectionsTestServiceAsync.java
+++ b/user/test/com/google/gwt/user/client/rpc/CollectionsTestServiceAsync.java
@@ -21,6 +21,7 @@
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Vector;
@@ -58,6 +59,9 @@
void echo(HashMap<String, IsSerializable> value,
AsyncCallback<HashMap<String, IsSerializable>> callback);
+ void echo(LinkedHashMap<String, IsSerializable> value,
+ AsyncCallback<LinkedHashMap<String, IsSerializable>> callback);
+
void echo(HashSet<IsSerializable> value,
AsyncCallback<HashSet<IsSerializable>> callback);
diff --git a/user/test/com/google/gwt/user/client/rpc/TestSetFactory.java b/user/test/com/google/gwt/user/client/rpc/TestSetFactory.java
index cbe483d..d5da927 100644
--- a/user/test/com/google/gwt/user/client/rpc/TestSetFactory.java
+++ b/user/test/com/google/gwt/user/client/rpc/TestSetFactory.java
@@ -22,6 +22,7 @@
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Vector;
@@ -262,6 +263,27 @@
return map;
}
+ public static LinkedHashMap createLRULinkedHashMap() {
+ LinkedHashMap map = new LinkedHashMap(100, 1.0f, true);
+ map.put("SerializableNode", new SerializableNode());
+ map.put("SerializableList", new SerializableList());
+ map.put("SerializableMap", new SerializableMap());
+ map.put("SerializableSet", new SerializableSet());
+ map.put("SerializableVector", new SerializableVector());
+ map.get("SerializableMap");
+ return map;
+ }
+
+ public static LinkedHashMap createLinkedHashMap() {
+ LinkedHashMap map = new LinkedHashMap();
+ map.put("SerializableNode", new SerializableNode());
+ map.put("SerializableList", new SerializableList());
+ map.put("SerializableMap", new SerializableMap());
+ map.put("SerializableSet", new SerializableSet());
+ map.put("SerializableVector", new SerializableVector());
+ return map;
+ }
+
public static HashSet createHashSet() {
HashSet set = new HashSet();
set.add(new SerializableNode());
diff --git a/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java b/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java
index dd663fb..d210669 100644
--- a/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java
+++ b/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java
@@ -24,6 +24,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -35,6 +36,15 @@
*/
public class TestSetValidator {
+ public static boolean equals(Iterator expected, Iterator actual) {
+ while (expected.hasNext() && actual.hasNext()) {
+ if (!expected.next().equals(actual.next())) {
+ return false;
+ }
+ }
+ return expected.hasNext() == actual.hasNext();
+ }
+
public static boolean equals(boolean[] expected, boolean[] actual) {
if (actual == null) {
return false;
@@ -276,6 +286,15 @@
return true;
}
+ public static boolean isValid(LinkedHashMap expected, LinkedHashMap map) {
+ if (isValid((Map) expected, (HashMap) map)) {
+ Iterator expectedEntries = expected.entrySet().iterator();
+ Iterator actualEntries = map.entrySet().iterator();
+ return equals(expectedEntries, actualEntries);
+ }
+ return false;
+ }
+
public static boolean isValid(SerializableClass actual) {
if (actual == null) {
return false;
diff --git a/user/test/com/google/gwt/user/server/rpc/CollectionsTestServiceImpl.java b/user/test/com/google/gwt/user/server/rpc/CollectionsTestServiceImpl.java
index c002e2e..cd61558 100644
--- a/user/test/com/google/gwt/user/server/rpc/CollectionsTestServiceImpl.java
+++ b/user/test/com/google/gwt/user/server/rpc/CollectionsTestServiceImpl.java
@@ -26,6 +26,7 @@
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Vector;
@@ -184,6 +185,17 @@
}
@SuppressWarnings("unchecked")
+ public LinkedHashMap echo(LinkedHashMap actual)
+ throws CollectionsTestServiceException {
+ HashMap expected = TestSetFactory.createLinkedHashMap();
+ if (!TestSetValidator.isValid(expected, actual)) {
+ throw new CollectionsTestServiceException("expected:"
+ + expected.toString() + " actual:" + actual.toString());
+ }
+ return actual;
+ }
+
+ @SuppressWarnings("unchecked")
public HashSet echo(HashSet actual) throws CollectionsTestServiceException {
HashSet expected = TestSetFactory.createHashSet();
if (!TestSetValidator.isValid(expected, actual)) {