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 org.apache.harmony.luni.tests.java.util;
19
20import dalvik.annotation.TestTargets;
21import dalvik.annotation.TestLevel;
22import dalvik.annotation.TestTargetNew;
23import dalvik.annotation.TestTargetClass;
24
25import java.util.AbstractMap;
26import java.util.AbstractSet;
27import java.util.Collections;
28import java.util.Comparator;
29import java.util.HashMap;
30import java.util.HashSet;
31import java.util.Hashtable;
32import java.util.IdentityHashMap;
33import java.util.Iterator;
34import java.util.LinkedHashMap;
35import java.util.Map;
36import java.util.Set;
37import java.util.TreeMap;
38import java.util.Vector;
39import java.util.WeakHashMap;
40
41@TestTargetClass(java.util.AbstractMap.class)
42public class AbstractMapTest extends junit.framework.TestCase {
43
44    static final String specialKey = "specialKey".intern();
45
46    static final String specialValue = "specialValue".intern();
47
48    // The impl of MyMap is not realistic, but serves to create a type
49    // that uses the default remove behavior.
50    class MyMap extends AbstractMap {
51        final Set mySet = new HashSet(1);
52
53        MyMap() {
54            mySet.add(new Map.Entry() {
55                public Object getKey() {
56                    return specialKey;
57                }
58
59                public Object getValue() {
60                    return specialValue;
61                }
62
63                public Object setValue(Object object) {
64                    return null;
65                }
66            });
67        }
68
69        public Object put(Object key, Object value) {
70            return null;
71        }
72
73        public Set entrySet() {
74            return mySet;
75        }
76    }
77
78    /**
79     * @tests java.util.AbstractMap#keySet()
80     */
81    @TestTargetNew(
82        level = TestLevel.COMPLETE,
83        notes = "Class is abstract. Functionality tested in subclasses for example in java.util.HashMap.",
84        method = "keySet",
85        args = {}
86    )
87    public void test_keySet() {
88        AbstractMap map1 = new HashMap(0);
89        assertSame("HashMap(0)", map1.keySet(), map1.keySet());
90
91        AbstractMap map2 = new HashMap(10);
92        assertSame("HashMap(10)", map2.keySet(), map2.keySet());
93
94        Map map3 = Collections.EMPTY_MAP;
95        assertSame("EMPTY_MAP", map3.keySet(), map3.keySet());
96
97        AbstractMap map4 = new IdentityHashMap(1);
98        assertSame("IdentityHashMap", map4.keySet(), map4.keySet());
99
100        AbstractMap map5 = new LinkedHashMap(122);
101        assertSame("LinkedHashMap", map5.keySet(), map5.keySet());
102
103        AbstractMap map6 = new TreeMap();
104        assertSame("TreeMap", map6.keySet(), map6.keySet());
105
106        AbstractMap map7 = new WeakHashMap();
107        assertSame("WeakHashMap", map7.keySet(), map7.keySet());
108    }
109
110    /**
111     * @tests java.util.AbstractMap#remove(java.lang.Object)
112     */
113    @TestTargetNew(
114        level = TestLevel.COMPLETE,
115        notes = "Class is abstract. Functionality tested in subclasses for example in java.util.HashMap.",
116        method = "remove",
117        args = {java.lang.Object.class}
118    )
119    public void test_removeLjava_lang_Object() {
120        Object key = new Object();
121        Object value = new Object();
122
123        AbstractMap map1 = new HashMap(0);
124        map1.put("key", value);
125        assertSame("HashMap(0)", map1.remove("key"), value);
126
127        AbstractMap map4 = new IdentityHashMap(1);
128        map4.put(key, value);
129        assertSame("IdentityHashMap", map4.remove(key), value);
130
131        AbstractMap map5 = new LinkedHashMap(122);
132        map5.put(key, value);
133        assertSame("LinkedHashMap", map5.remove(key), value);
134
135        AbstractMap map6 = new TreeMap(new Comparator() {
136            // Bogus comparator
137            public int compare(Object object1, Object object2) {
138                return 0;
139            }
140        });
141        map6.put(key, value);
142        assertSame("TreeMap", map6.remove(key), value);
143
144        AbstractMap map7 = new WeakHashMap();
145        map7.put(key, value);
146        assertSame("WeakHashMap", map7.remove(key), value);
147
148        AbstractMap aSpecialMap = new MyMap();
149        aSpecialMap.put(specialKey, specialValue);
150        Object valueOut = aSpecialMap.remove(specialKey);
151        assertSame("MyMap", valueOut, specialValue);
152    }
153
154    /**
155     * @tests java.util.AbstractMap#values()
156     */
157    @TestTargetNew(
158        level = TestLevel.COMPLETE,
159        notes = "Class is abstract. Functionality tested in subclasses for example in java.util.HashMap.",
160        method = "values",
161        args = {}
162    )
163    public void test_values() {
164        AbstractMap map1 = new HashMap(0);
165        assertSame("HashMap(0)", map1.values(), map1.values());
166
167        AbstractMap map2 = new HashMap(10);
168        assertSame("HashMap(10)", map2.values(), map2.values());
169
170        Map map3 = Collections.EMPTY_MAP;
171        assertSame("EMPTY_MAP", map3.values(), map3.values());
172
173        AbstractMap map4 = new IdentityHashMap(1);
174        assertSame("IdentityHashMap", map4.values(), map4.values());
175
176        AbstractMap map5 = new LinkedHashMap(122);
177        assertSame("IdentityHashMap", map5.values(), map5.values());
178
179        AbstractMap map6 = new TreeMap();
180        assertSame("TreeMap", map6.values(), map6.values());
181
182        AbstractMap map7 = new WeakHashMap();
183        assertSame("WeakHashMap", map7.values(), map7.values());
184    }
185
186    /**
187     * @tests java.util.AbstractMap#clone()
188     */
189    @TestTargetNew(
190        level = TestLevel.COMPLETE,
191        notes = "Class is abstract. Functionality tested in subclasses for example in java.util.HashMap.",
192        method = "clone",
193        args = {}
194    )
195    public void test_clone() {
196        class MyMap extends AbstractMap implements Cloneable {
197            private Map map = new HashMap();
198
199            public Set entrySet() {
200                return map.entrySet();
201            }
202
203            public Object put(Object key, Object value) {
204                return map.put(key, value);
205            }
206
207            public Map getMap() {
208                return map;
209            }
210
211            public Object clone() {
212                try {
213                    return super.clone();
214                } catch (CloneNotSupportedException e) {
215                    throw new AssertionError(e); // android-changed
216                }
217            }
218        }
219        ;
220        MyMap map = new MyMap();
221        map.put("one", "1");
222        Map.Entry entry = (Map.Entry) map.entrySet().iterator().next();
223        assertTrue("entry not added", entry.getKey() == "one"
224                && entry.getValue() == "1");
225        MyMap mapClone = (MyMap) map.clone();
226        assertTrue("clone not shallow", map.getMap() == mapClone.getMap());
227    }
228
229    class MocAbstractMap<K, V> extends AbstractMap {
230
231        public Set entrySet() {
232            Set set = new MySet();
233            return set;
234        }
235
236        class MySet extends HashSet {
237            public void clear() {
238                throw new UnsupportedOperationException();
239            }
240        }
241    }
242
243    @TestTargetNew(
244        level = TestLevel.COMPLETE,
245        notes = "Class is abstract. Functionality tested in subclasses for example in java.util.HashMap.",
246        method = "clear",
247        args = {}
248    )
249    public void test_clear() {
250        // normal clear()
251        AbstractMap map = new HashMap();
252        map.put(1, 1);
253        map.clear();
254        assertTrue(map.isEmpty());
255
256        // Special entrySet return a Set with no clear method.
257        AbstractMap myMap = new MocAbstractMap();
258        try {
259            myMap.clear();
260            fail("Should throw UnsupportedOprationException");
261        } catch (UnsupportedOperationException e) {
262            // expected
263        }
264    }
265
266    /**
267     * @tests java.util.AbstractMap#containsKey(Object)
268     */
269    @TestTargetNew(
270        level = TestLevel.COMPLETE,
271        notes = "Class is abstract. Functionality tested in subclasses for example in java.util.HashMap.",
272        method = "containsKey",
273        args = {java.lang.Object.class}
274    )
275    public void test_containsKey() {
276        AbstractMap map = new AMT();
277
278        assertFalse(map.containsKey("k"));
279        assertFalse(map.containsKey(null));
280
281        map.put("k", "v");
282        map.put("key", null);
283        map.put(null, "value");
284        map.put(null, null);
285
286        assertTrue(map.containsKey("k"));
287        assertTrue(map.containsKey("key"));
288        assertTrue(map.containsKey(null));
289    }
290
291    /**
292     * @tests java.util.AbstractMap#containsValue(Object)
293     */
294    @TestTargetNew(
295        level = TestLevel.COMPLETE,
296        notes = "Class is abstract. Functionality tested in subclasses for example in java.util.HashMap.",
297        method = "containsValue",
298        args = {java.lang.Object.class}
299    )
300    public void test_containValue() {
301        AbstractMap map = new AMT();
302
303        assertFalse(map.containsValue("v"));
304        assertFalse(map.containsValue(null));
305
306        map.put("k", "v");
307        map.put("key", null);
308        map.put(null, "value");
309
310        assertTrue(map.containsValue("v"));
311        assertTrue(map.containsValue("value"));
312        assertTrue(map.containsValue(null));
313    }
314
315    /**
316     * @tests java.util.AbstractMap#get(Object)
317     */
318    @TestTargetNew(
319        level = TestLevel.COMPLETE,
320        notes = "Class is abstract. Functionality tested in subclasses for example in java.util.HashMap.",
321        method = "get",
322        args = {java.lang.Object.class}
323    )
324    public void test_get() {
325        AbstractMap map = new AMT();
326        assertNull(map.get("key"));
327        assertNull(map.get(null));
328
329        map.put("k", "v");
330        map.put("key", null);
331        map.put(null, "value");
332
333        assertEquals("v", map.get("k"));
334        assertNull(map.get("key"));
335        assertEquals("value", map.get(null));
336    }
337
338    public class AMT extends AbstractMap {
339
340        // Very crude AbstractMap implementation
341        Vector values = new Vector();
342
343        Vector keys = new Vector();
344
345        public Set entrySet() {
346            return new AbstractSet() {
347                public Iterator iterator() {
348                    return new Iterator() {
349                        int index = 0;
350
351                        public boolean hasNext() {
352                            return index < values.size();
353                        }
354
355                        public Object next() {
356                            if (index < values.size()) {
357                                Map.Entry me = new Map.Entry() {
358                                    Object v = values.elementAt(index);
359
360                                    Object k = keys.elementAt(index);
361
362                                    public Object getKey() {
363                                        return k;
364                                    }
365
366                                    public Object getValue() {
367                                        return v;
368                                    }
369
370                                    public Object setValue(Object value) {
371                                        return null;
372                                    }
373                                };
374                                index++;
375                                return me;
376                            }
377                            return null;
378                        }
379
380                        public void remove() {
381                        }
382                    };
383                }
384
385                public int size() {
386                    return values.size();
387                }
388            };
389        }
390
391        public Object put(Object k, Object v) {
392            keys.add(k);
393            values.add(v);
394            return v;
395        }
396    }
397
398    /**
399     * @tests {@link java.util.AbstractMap#putAll(Map)}
400     */
401    @TestTargetNew(
402        level = TestLevel.COMPLETE,
403        notes = "Class is abstract. Functionality tested in subclasses for example in java.util.HashMap.",
404        method = "putAll",
405        args = {java.util.Map.class}
406    )
407    public void test_putAllLMap() {
408        Hashtable ht = new Hashtable();
409        AbstractMap amt = new AMT();
410        ht.put("this", "that");
411        amt.putAll(ht);
412        assertEquals("Should be equal", amt, ht);
413    }
414
415    @TestTargetNew(
416        level = TestLevel.COMPLETE,
417        notes = "Class is abstract. Functionality tested in subclasses for example in java.util.HashMap.",
418        method = "AbstractMap",
419        args = {}
420    )
421    public void test_Constructor() {
422        AMT amt = new AMT();
423        assertNotNull(amt);
424    }
425
426    @TestTargetNew(
427        level = TestLevel.COMPLETE,
428        notes = "Class is abstract. Functionality tested in subclasses for example in java.util.HashMap.",
429        method = "equals",
430        args = {java.lang.Object.class}
431    )
432    public void test_equalsLjava_lang_Object() {
433        AbstractMap amt1 = new AMT();
434        AbstractMap amt2 = new AMT();
435        assertTrue("assert 0", amt1.equals(amt2));
436        assertTrue("assert 1", amt1.equals(amt1));
437        assertTrue("assert 2", amt2.equals(amt1));
438        amt1.put("1", "one");
439        assertFalse("assert 3", amt1.equals(amt2));
440        amt1.put("2", "two");
441        amt1.put("3", "three");
442
443        amt2.put("1", "one");
444        amt2.put("2", "two");
445        amt2.put("3", "three");
446        assertTrue("assert 4", amt1.equals(amt2));
447        assertFalse("assert 5", amt1.equals(this));
448    }
449
450    @TestTargetNew(
451        level = TestLevel.COMPLETE,
452        notes = "Class is abstract. Functionality tested in subclasses for example in java.util.HashMap.",
453        method = "hashCode",
454        args = {}
455    )
456    public void test_hashCode() {
457        AMT amt1 = new AMT();
458        AMT amt2 = new AMT();
459        amt1.put("1", "one");
460
461        assertNotSame(amt1.hashCode(), amt2.hashCode());
462    }
463
464    @TestTargetNew(
465        level = TestLevel.COMPLETE,
466        notes = "Class is abstract. Functionality tested in subclasses for example in java.util.HashMap.",
467        method = "isEmpty",
468        args = {}
469    )
470    public void test_isEmpty() {
471        AMT amt = new AMT();
472        assertTrue(amt.isEmpty());
473        amt.put("1", "one");
474        assertFalse(amt.isEmpty());
475    }
476
477    @TestTargetNew(
478        level = TestLevel.COMPLETE,
479        notes = "Class is abstract. Functionality tested in subclasses for example in java.util.HashMap.",
480        method = "put",
481        args = {java.lang.Object.class, java.lang.Object.class}
482    )
483    public void test_put() {
484        AMT amt = new AMT();
485        assertEquals(0, amt.size());
486        amt.put("1", "one");
487        assertEquals(1, amt.size());
488        amt.put("2", "two");
489        assertEquals(2, amt.size());
490        amt.put("3", "three");
491        assertEquals(3, amt.size());
492    }
493
494    @TestTargetNew(
495        level = TestLevel.COMPLETE,
496        notes = "Class is abstract. Functionality tested in subclasses for example in java.util.HashMap.",
497        method = "size",
498        args = {}
499    )
500    public void test_size() {
501        AMT amt = new AMT();
502        assertEquals(0, amt.size());
503        amt.put("1", "one");
504        assertEquals(1, amt.size());
505        amt.put("2", "two");
506        assertEquals(2, amt.size());
507        amt.put("3", "three");
508        assertEquals(3, amt.size());
509    }
510
511    @TestTargetNew(
512        level = TestLevel.COMPLETE,
513        notes = "Class is abstract. Functionality tested in subclasses for example in java.util.HashMap.",
514        method = "toString",
515        args = {}
516    )
517    public void test_toString() {
518        AMT amt = new AMT();
519        assertEquals("{}", amt.toString());
520        amt.put("1", "one");
521        assertEquals("{1=one}", amt.toString());
522        amt.put("2", "two");
523        assertEquals("{1=one, 2=two}", amt.toString());
524        amt.put("3", "three");
525        assertEquals("{1=one, 2=two, 3=three}", amt.toString());
526    }
527
528    protected void setUp() {
529    }
530
531    protected void tearDown() {
532    }
533}
534