1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package tests.api.java.util;
19
20import java.util.AbstractMap;
21import java.util.AbstractSet;
22import java.util.Collection;
23import java.util.Collections;
24import java.util.Comparator;
25import java.util.HashMap;
26import java.util.HashSet;
27import java.util.Hashtable;
28import java.util.IdentityHashMap;
29import java.util.Iterator;
30import java.util.LinkedHashMap;
31import java.util.Map;
32import java.util.Set;
33import java.util.TreeMap;
34import java.util.Vector;
35import java.util.WeakHashMap;
36
37public class AbstractMapTest extends junit.framework.TestCase {
38
39    static final String specialKey = "specialKey".intern();
40
41    static final String specialValue = "specialValue".intern();
42
43    // The impl of MyMap is not realistic, but serves to create a type
44    // that uses the default remove behavior.
45    class MyMap extends AbstractMap {
46        final Set mySet = new HashSet(1);
47
48        MyMap() {
49            mySet.add(new Map.Entry() {
50                public Object getKey() {
51                    return specialKey;
52                }
53
54                public Object getValue() {
55                    return specialValue;
56                }
57
58                public Object setValue(Object object) {
59                    return null;
60                }
61            });
62        }
63
64        public Object put(Object key, Object value) {
65            return null;
66        }
67
68        public Set entrySet() {
69            return mySet;
70        }
71    }
72
73    /**
74     * java.util.AbstractMap#keySet()
75     */
76    public void test_keySet() {
77        AbstractMap map1 = new HashMap(0);
78        assertSame("HashMap(0)", map1.keySet(), map1.keySet());
79
80        AbstractMap map2 = new HashMap(10);
81        assertSame("HashMap(10)", map2.keySet(), map2.keySet());
82
83        Map map3 = Collections.EMPTY_MAP;
84        assertSame("EMPTY_MAP", map3.keySet(), map3.keySet());
85
86        AbstractMap map4 = new IdentityHashMap(1);
87        assertSame("IdentityHashMap", map4.keySet(), map4.keySet());
88
89        AbstractMap map5 = new LinkedHashMap(122);
90        assertSame("LinkedHashMap", map5.keySet(), map5.keySet());
91
92        AbstractMap map6 = new TreeMap();
93        assertSame("TreeMap", map6.keySet(), map6.keySet());
94
95        AbstractMap map7 = new WeakHashMap();
96        assertSame("WeakHashMap", map7.keySet(), map7.keySet());
97    }
98
99    /**
100     * java.util.AbstractMap#remove(java.lang.Object)
101     */
102    public void test_removeLjava_lang_Object() {
103        Object key = new Object();
104        Object value = new Object();
105
106        AbstractMap map1 = new HashMap(0);
107        map1.put("key", value);
108        assertSame("HashMap(0)", map1.remove("key"), value);
109
110        AbstractMap map4 = new IdentityHashMap(1);
111        map4.put(key, value);
112        assertSame("IdentityHashMap", map4.remove(key), value);
113
114        AbstractMap map5 = new LinkedHashMap(122);
115        map5.put(key, value);
116        assertSame("LinkedHashMap", map5.remove(key), value);
117
118        AbstractMap map6 = new TreeMap(new Comparator() {
119            // Bogus comparator
120            public int compare(Object object1, Object object2) {
121                return 0;
122            }
123        });
124        map6.put(key, value);
125        assertSame("TreeMap", map6.remove(key), value);
126
127        AbstractMap map7 = new WeakHashMap();
128        map7.put(key, value);
129        assertSame("WeakHashMap", map7.remove(key), value);
130
131        AbstractMap aSpecialMap = new MyMap();
132        aSpecialMap.put(specialKey, specialValue);
133        Object valueOut = aSpecialMap.remove(specialKey);
134        assertSame("MyMap", valueOut, specialValue);
135    }
136
137    /**
138     * java.util.AbstractMap#values()
139     */
140    public void test_values() {
141        AbstractMap map1 = new HashMap(0);
142        assertSame("HashMap(0)", map1.values(), map1.values());
143
144        AbstractMap map2 = new HashMap(10);
145        assertSame("HashMap(10)", map2.values(), map2.values());
146
147        Map map3 = Collections.EMPTY_MAP;
148        assertSame("EMPTY_MAP", map3.values(), map3.values());
149
150        AbstractMap map4 = new IdentityHashMap(1);
151        assertSame("IdentityHashMap", map4.values(), map4.values());
152
153        AbstractMap map5 = new LinkedHashMap(122);
154        assertSame("IdentityHashMap", map5.values(), map5.values());
155
156        AbstractMap map6 = new TreeMap();
157        assertSame("TreeMap", map6.values(), map6.values());
158
159        AbstractMap map7 = new WeakHashMap();
160        assertSame("WeakHashMap", map7.values(), map7.values());
161    }
162
163    /**
164     * java.util.AbstractMap#clone()
165     */
166    public void test_clone() {
167        class MyMap extends AbstractMap implements Cloneable {
168            private Map map = new HashMap();
169
170            public Set entrySet() {
171                return map.entrySet();
172            }
173
174            public Object put(Object key, Object value) {
175                return map.put(key, value);
176            }
177
178            public Map getMap() {
179                return map;
180            }
181
182            public Object clone() {
183                try {
184                    return super.clone();
185                } catch (CloneNotSupportedException e) {
186                    throw new AssertionError(e); // android-changed
187                }
188            }
189        }
190        ;
191        MyMap map = new MyMap();
192        map.put("one", "1");
193        Map.Entry entry = (Map.Entry) map.entrySet().iterator().next();
194        assertTrue("entry not added", entry.getKey() == "one"
195                && entry.getValue() == "1");
196        MyMap mapClone = (MyMap) map.clone();
197        assertTrue("clone not shallow", map.getMap() == mapClone.getMap());
198    }
199
200    public class AMT extends AbstractMap {
201
202        // Very crude AbstractMap implementation
203        Vector values = new Vector();
204        Vector keys   = new Vector();
205
206        public Set entrySet() {
207            return new AbstractSet() {
208                public Iterator iterator() {
209                    return new Iterator() {
210                        int index = 0;
211
212                        public boolean hasNext() {
213                            return index < values.size();
214                        }
215
216                        public Object next() {
217                            if (index < values.size()) {
218                                Map.Entry me = new Map.Entry() {
219                                    Object v = values.elementAt(index);
220
221                                    Object k = keys.elementAt(index);
222
223                                    public Object getKey() {
224                                        return k;
225                                    }
226
227                                    public Object getValue() {
228                                        return v;
229                                    }
230
231                                    public Object setValue(Object value) {
232                                        return null;
233                                    }
234                                };
235                                index++;
236                                return me;
237                            }
238                            return null;
239                        }
240
241                        public void remove() {
242                        }
243                    };
244                }
245
246                public int size() {
247                    return values.size();
248                }
249            };
250        }
251
252        public Object put(Object k, Object v) {
253            keys.add(k);
254            values.add(v);
255            return v;
256        }
257    }
258
259    /**
260     * {@link java.util.AbstractMap#putAll(Map)}
261     */
262    public void test_putAllLMap() {
263        Hashtable ht  = new Hashtable();
264        AMT amt = new AMT();
265        ht.put("this", "that");
266        amt.putAll(ht);
267
268        assertEquals("Should be equal", amt, ht);
269    }
270
271    public void testEqualsWithNullValues() {
272        Map<String, String> a = new HashMap<String, String>();
273        a.put("a", null);
274        a.put("b", null);
275
276        Map<String, String> b = new HashMap<String, String>();
277        a.put("c", "cat");
278        a.put("d", "dog");
279
280        assertFalse(a.equals(b));
281        assertFalse(b.equals(a));
282    }
283
284    public void testNullsOnViews() {
285        Map<String, String> nullHostile = new Hashtable<String, String>();
286
287        nullHostile.put("a", "apple");
288        testNullsOnView(nullHostile.entrySet());
289
290        nullHostile.put("a", "apple");
291        testNullsOnView(nullHostile.keySet());
292
293        nullHostile.put("a", "apple");
294        testNullsOnView(nullHostile.values());
295    }
296
297    private void testNullsOnView(Collection<?> view) {
298        try {
299            assertFalse(view.contains(null));
300        } catch (NullPointerException optional) {
301        }
302
303        try {
304            assertFalse(view.remove(null));
305        } catch (NullPointerException optional) {
306        }
307
308        Set<Object> setOfNull = Collections.singleton(null);
309        assertFalse(view.equals(setOfNull));
310
311        try {
312            assertFalse(view.removeAll(setOfNull));
313        } catch (NullPointerException optional) {
314        }
315
316        try {
317            assertTrue(view.retainAll(setOfNull)); // destructive
318        } catch (NullPointerException optional) {
319        }
320    }
321
322    protected void setUp() {
323    }
324
325    protected void tearDown() {
326    }
327}
328