WeakHashMapTest.java revision 561ee011997c6c2f1befbfaa9d5f0a99771c1d63
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 java.lang.ref.ReferenceQueue;
21import java.lang.ref.WeakReference;
22import java.util.AbstractMap;
23import java.util.Arrays;
24import java.util.Collection;
25import java.util.Iterator;
26import java.util.List;
27import java.util.Map;
28import java.util.Set;
29import java.util.WeakHashMap;
30import tests.support.Support_MapTest2;
31
32public class WeakHashMapTest extends junit.framework.TestCase {
33	class MockMap extends AbstractMap {
34		public Set entrySet() {
35			return null;
36		}
37		public int size(){
38			return 0;
39		}
40	}
41
42	Object[] keyArray = new Object[100];
43
44	Object[] valueArray = new Object[100];
45
46	WeakHashMap whm;
47
48    Object[] KEY_ARRAY;
49
50    Object[] VALUE_ARRAY;
51
52	/**
53	 * @tests java.util.WeakHashMap#WeakHashMap()
54	 */
55	public void test_Constructor() {
56		// Test for method java.util.WeakHashMap()
57		new Support_MapTest2(new WeakHashMap()).runTest();
58
59		whm = new WeakHashMap();
60		for (int i = 0; i < 100; i++)
61			whm.put(keyArray[i], valueArray[i]);
62		for (int i = 0; i < 100; i++)
63			assertTrue("Incorrect value retrieved",
64					whm.get(keyArray[i]) == valueArray[i]);
65
66	}
67
68	/**
69	 * @tests java.util.WeakHashMap#WeakHashMap(int)
70	 */
71	public void test_ConstructorI() {
72		// Test for method java.util.WeakHashMap(int)
73		whm = new WeakHashMap(50);
74		for (int i = 0; i < 100; i++)
75			whm.put(keyArray[i], valueArray[i]);
76		for (int i = 0; i < 100; i++)
77			assertTrue("Incorrect value retrieved",
78					whm.get(keyArray[i]) == valueArray[i]);
79
80		WeakHashMap empty = new WeakHashMap(0);
81		assertNull("Empty weakhashmap access", empty.get("nothing"));
82		empty.put("something", "here");
83		assertTrue("cannot get element", empty.get("something") == "here");
84	}
85
86	/**
87	 * @tests java.util.WeakHashMap#WeakHashMap(int, float)
88	 */
89	public void test_ConstructorIF() {
90		// Test for method java.util.WeakHashMap(int, float)
91		whm = new WeakHashMap(50, 0.5f);
92		for (int i = 0; i < 100; i++)
93			whm.put(keyArray[i], valueArray[i]);
94		for (int i = 0; i < 100; i++)
95			assertTrue("Incorrect value retrieved",
96					whm.get(keyArray[i]) == valueArray[i]);
97
98		WeakHashMap empty = new WeakHashMap(0, 0.75f);
99		assertNull("Empty hashtable access", empty.get("nothing"));
100		empty.put("something", "here");
101		assertTrue("cannot get element", empty.get("something") == "here");
102	}
103
104	/**
105	 * @tests java.util.WeakHashMap#WeakHashMap(java.util.Map)
106	 */
107	public void test_ConstructorLjava_util_Map() {
108        Map mockMap = new MockMap();
109        WeakHashMap map = new WeakHashMap(mockMap);
110        assertEquals("Size should be 0", 0, map.size());
111	}
112
113	/**
114	 * @tests java.util.WeakHashMap#clear()
115	 */
116	public void test_clear() {
117		// Test for method boolean java.util.WeakHashMap.clear()
118		whm = new WeakHashMap();
119		for (int i = 0; i < 100; i++)
120			whm.put(keyArray[i], valueArray[i]);
121		whm.clear();
122		assertTrue("Cleared map should be empty", whm.isEmpty());
123		for (int i = 0; i < 100; i++)
124			assertNull("Cleared map should only return null", whm
125					.get(keyArray[i]));
126
127	}
128
129	/**
130	 * @tests java.util.WeakHashMap#containsKey(java.lang.Object)
131	 */
132	public void test_containsKeyLjava_lang_Object() {
133		// Test for method boolean java.util.WeakHashMap.containsKey()
134		whm = new WeakHashMap();
135		for (int i = 0; i < 100; i++)
136			whm.put(keyArray[i], valueArray[i]);
137		for (int i = 0; i < 100; i++)
138			assertTrue("Should contain referenced key", whm
139					.containsKey(keyArray[i]));
140		keyArray[25] = null;
141		keyArray[50] = null;
142	}
143
144	/**
145	 * @tests java.util.WeakHashMap#containsValue(java.lang.Object)
146	 */
147	public void test_containsValueLjava_lang_Object() {
148		// Test for method boolean java.util.WeakHashMap.containsValue()
149		whm = new WeakHashMap();
150		for (int i = 0; i < 100; i++)
151			whm.put(keyArray[i], valueArray[i]);
152		for (int i = 0; i < 100; i++)
153			assertTrue("Should contain referenced value", whm
154					.containsValue(valueArray[i]));
155		keyArray[25] = null;
156		keyArray[50] = null;
157	}
158
159    /**
160     * @tests java.util.WeakHashMap#entrySet()
161     */
162    public void test_entrySet() {
163        WeakHashMap<Object, Object> weakMap = new WeakHashMap<Object, Object>();
164        KEY_ARRAY = new Object[100];
165        VALUE_ARRAY = new Object[100];
166        for (int i = 0; i < 100; i++) {
167            KEY_ARRAY[i] = new Integer(i);
168            VALUE_ARRAY[i] = new Long(i);
169            weakMap.put(KEY_ARRAY[i], VALUE_ARRAY[i]);
170        }
171
172        List<Object> keys = Arrays.asList(KEY_ARRAY);
173        List<Object> values = Arrays.asList(VALUE_ARRAY);
174
175        // Check the entry set has correct size & content
176        Set<Map.Entry<Object, Object>> entrySet = weakMap.entrySet();
177        assertEquals("Assert 0: Incorrect number of entries returned", 100,
178                entrySet.size());
179        Iterator<Map.Entry<Object, Object>> it = entrySet.iterator();
180        while (it.hasNext()) {
181            Map.Entry<Object, Object> entry = it.next();
182            assertTrue("Assert 1: Invalid map entry key returned", keys
183                    .contains(entry.getKey()));
184            assertTrue("Assert 2: Invalid map entry value returned", values
185                    .contains(entry.getValue()));
186            assertTrue("Assert 3: Entry not in entry set", entrySet
187                    .contains(entry));
188        }
189
190        // Dereference list of key/value objects
191        keys = values = null;
192
193        // Dereference a single key, then try to
194        // force a collection of the weak ref'd obj
195        KEY_ARRAY[50] = null;
196        enqueueWeakReferences();
197
198        assertEquals("Assert 4: Incorrect number of entries after gc", 99,
199                entrySet.size());
200        assertSame("Assert 5: Entries not identical", entrySet.iterator()
201                .next(), entrySet.iterator().next());
202
203        // remove alternate entries using the iterator, and ensure the
204        // iteration count is consistent
205        int size = entrySet.size();
206        it = entrySet.iterator();
207        while (it.hasNext()) {
208            it.next();
209            it.remove();
210            size--;
211            if (it.hasNext()) {
212                it.next();
213            }
214
215        }
216        assertEquals("Assert 6: entry set count mismatch", size, entrySet
217                .size());
218
219        int entries = 0;
220        it = entrySet.iterator();
221        while (it.hasNext()) {
222            it.next();
223            entries++;
224        }
225        assertEquals("Assert 6: count mismatch", size, entries);
226
227        it = entrySet.iterator();
228        while (it.hasNext()) {
229            it.next();
230            it.remove();
231        }
232        assertEquals("Assert 7: entry set not empty", 0, entrySet.size());
233        assertTrue("Assert 8:  iterator not empty", !entrySet.iterator()
234                .hasNext());
235    }
236
237	/**
238	 * @tests java.util.WeakHashMap#entrySet()
239	 */
240	public void test_entrySet_2() {
241		// Test for method java.util.Set java.util.WeakHashMap.entrySet()
242		whm = new WeakHashMap();
243		for (int i = 0; i < 100; i++)
244			whm.put(keyArray[i], valueArray[i]);
245		List keys = Arrays.asList(keyArray);
246		List values = Arrays.asList(valueArray);
247		Set entrySet = whm.entrySet();
248		assertTrue("Incorrect number of entries returned--wanted 100, got: "
249				+ entrySet.size(), entrySet.size() == 100);
250		Iterator it = entrySet.iterator();
251		while (it.hasNext()) {
252			Map.Entry entry = (Map.Entry) it.next();
253			assertTrue("Invalid map entry returned--bad key", keys
254					.contains(entry.getKey()));
255			assertTrue("Invalid map entry returned--bad key", values
256					.contains(entry.getValue()));
257		}
258		keys = null;
259		values = null;
260		keyArray[50] = null;
261
262        enqueueWeakReferences();
263
264		assertTrue(
265				"Incorrect number of entries returned after gc--wanted 99, got: "
266						+ entrySet.size(), entrySet.size() == 99);
267	}
268
269	/**
270	 * @tests java.util.WeakHashMap#get(java.lang.Object)
271	 */
272	public void test_getLjava_lang_Object() {
273		// Test for method java.lang.Object
274		// java.util.WeakHashMap.get(java.lang.Object)
275		assertTrue("Used to test", true);
276	}
277
278	/**
279	 * @tests java.util.WeakHashMap#isEmpty()
280	 */
281	public void test_isEmpty() {
282		// Test for method boolean java.util.WeakHashMap.isEmpty()
283		whm = new WeakHashMap();
284		assertTrue("New map should be empty", whm.isEmpty());
285		Object myObject = new Object();
286		whm.put(myObject, myObject);
287		assertTrue("Map should not be empty", !whm.isEmpty());
288		whm.remove(myObject);
289		assertTrue("Map with elements removed should be empty", whm.isEmpty());
290	}
291
292	/**
293	 * @tests java.util.WeakHashMap#put(java.lang.Object, java.lang.Object)
294	 */
295	public void test_putLjava_lang_ObjectLjava_lang_Object() {
296		// Test for method java.lang.Object
297		// java.util.WeakHashMap.put(java.lang.Object, java.lang.Object)
298		WeakHashMap map = new WeakHashMap();
299		map.put(null, "value"); // add null key
300        enqueueWeakReferences();
301		map.remove("nothing"); // Cause objects in queue to be removed
302		assertEquals("null key was removed", 1, map.size());
303	}
304
305    /**
306     * @tests java.util.WeakHashMap#putAll(java.util.Map)
307     */
308    public void test_putAllLjava_util_Map() {
309        Map mockMap=new MockMap();
310        WeakHashMap map = new WeakHashMap();
311        map.putAll(mockMap);
312        assertEquals("Size should be 0", 0, map.size());
313    }
314
315	/**
316	 * @tests java.util.WeakHashMap#remove(java.lang.Object)
317	 */
318	public void test_removeLjava_lang_Object() {
319		// Test for method java.lang.Object
320		// java.util.WeakHashMap.remove(java.lang.Object)
321		whm = new WeakHashMap();
322		for (int i = 0; i < 100; i++)
323			whm.put(keyArray[i], valueArray[i]);
324
325		assertTrue("Remove returned incorrect value",
326				whm.remove(keyArray[25]) == valueArray[25]);
327		assertNull("Remove returned incorrect value",
328				whm.remove(keyArray[25]));
329		assertEquals("Size should be 99 after remove", 99, whm.size());
330	}
331
332	/**
333	 * @tests java.util.WeakHashMap#size()
334	 */
335	public void test_size() {
336		// Test for method int java.util.WeakHashMap.size()
337		assertTrue("Used to test", true);
338	}
339
340	/**
341	 * @tests java.util.WeakHashMap#keySet()
342	 */
343	public void test_keySet() {
344		// Test for method java.util.Set java.util.WeakHashMap.keySet()
345		whm = new WeakHashMap();
346		for (int i = 0; i < 100; i++)
347			whm.put(keyArray[i], valueArray[i]);
348
349		List keys = Arrays.asList(keyArray);
350		List values = Arrays.asList(valueArray);
351
352		Set keySet = whm.keySet();
353		assertEquals("Incorrect number of keys returned,", 100, keySet.size());
354		Iterator it = keySet.iterator();
355		while (it.hasNext()) {
356			Object key = it.next();
357			assertTrue("Invalid map entry returned--bad key", keys
358					.contains(key));
359		}
360		keys = null;
361		values = null;
362		keyArray[50] = null;
363
364        enqueueWeakReferences();
365
366		assertEquals("Incorrect number of keys returned after gc,", 99, keySet
367				.size());
368	}
369
370    /**
371     * Regression test for HARMONY-3883
372     * @tests java.util.WeakHashMap#keySet()
373     */
374    public void test_keySet_hasNext() {
375        WeakHashMap map = new WeakHashMap();
376        ConstantHashClass cl = new ConstantHashClass(2);
377        map.put(new ConstantHashClass(1), null);
378        map.put(cl, null);
379        map.put(new ConstantHashClass(3), null);
380        Iterator iter = map.keySet().iterator();
381        iter.next();
382        iter.next();
383        enqueueWeakReferences();
384        assertFalse("Wrong hasNext() value", iter.hasNext());
385    }
386
387    static class ConstantHashClass {
388        private int id = 0;
389
390        public ConstantHashClass(int id) {
391            this.id = id;
392        }
393
394        public int hashCode() {
395            return 0;
396        }
397
398        public String toString() {
399            return "ConstantHashClass[id=" + id + "]";
400        }
401    }
402
403
404	/**
405	 * @tests java.util.WeakHashMap#values()
406	 */
407	public void test_values() {
408		// Test for method java.util.Set java.util.WeakHashMap.values()
409		whm = new WeakHashMap();
410		for (int i = 0; i < 100; i++)
411			whm.put(keyArray[i], valueArray[i]);
412
413		List keys = Arrays.asList(keyArray);
414		List values = Arrays.asList(valueArray);
415
416		Collection valuesCollection = whm.values();
417		assertEquals("Incorrect number of keys returned,", 100,
418				valuesCollection.size());
419		Iterator it = valuesCollection.iterator();
420		while (it.hasNext()) {
421			Object value = it.next();
422			assertTrue("Invalid map entry returned--bad value", values
423					.contains(value));
424		}
425		keys = null;
426		values = null;
427		keyArray[50] = null;
428
429        enqueueWeakReferences();
430
431		assertEquals("Incorrect number of keys returned after gc,", 99,
432				valuesCollection.size());
433	}
434
435    /**
436     * Induce the VM to enqueue weak references into the corresponding reference
437     * queues. This guarantees that all weak hash maps can observe their own
438     * references as both cleared and enqueued.
439     *
440     * <p>This method assumes that one value enqueued implies all others will be
441     * enqueued. This behavior isn't specified, and this method may return too
442     * early on some VMs.
443     */
444    private void enqueueWeakReferences() {
445        ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
446        new WeakReference<Object>(new Object(), queue);
447        System.gc();
448        try {
449            queue.remove(200); // '200' shouldn't be necessary, but works on more VMs
450        } catch (InterruptedException e) {
451        }
452    }
453
454    /**
455	 * Sets up the fixture, for example, open a network connection. This method
456	 * is called before a test is executed.
457	 */
458	protected void setUp() {
459		for (int i = 0; i < 100; i++) {
460			keyArray[i] = new Object();
461			valueArray[i] = new Object();
462		}
463
464	}
465
466	/**
467	 * Tears down the fixture, for example, close a network connection. This
468	 * method is called after a test is executed.
469	 */
470	protected void tearDown() {
471	}
472}
473