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  
18  
19  package org.apache.commons.logging.impl;
20  
21  import java.lang.ref.*;
22  import junit.framework.*;
23  import java.util.*;
24  
25  public class WeakHashtableTest extends TestCase {
26  
27      
28      /** Maximum number of iterations before our test fails */
29      private static final int MAX_GC_ITERATIONS = 50;
30  
31      private WeakHashtable weakHashtable;
32      private Long keyOne;
33      private Long keyTwo;
34      private Long keyThree;
35      private Long valueOne;
36      private Long valueTwo;
37      private Long valueThree;
38  
39      public WeakHashtableTest(String testName) {
40          super(testName);
41      }
42      
43  
44      protected void setUp() throws Exception {
45          super.setUp();
46          weakHashtable = new WeakHashtable();
47          
48          keyOne = new Long(1);
49          keyTwo = new Long(2);
50          keyThree = new Long(3);
51          valueOne = new Long(100);
52          valueTwo = new Long(200);
53          valueThree = new Long(300);
54          
55          weakHashtable.put(keyOne, valueOne);
56          weakHashtable.put(keyTwo, valueTwo);
57          weakHashtable.put(keyThree, valueThree);
58      }
59  
60      /** Tests public boolean contains(Object value) */
61      public void testContains() throws Exception {
62          assertFalse(weakHashtable.contains(new Long(1)));
63          assertFalse(weakHashtable.contains(new Long(2)));
64          assertFalse(weakHashtable.contains(new Long(3)));
65          assertTrue(weakHashtable.contains(new Long(100)));
66          assertTrue(weakHashtable.contains(new Long(200)));
67          assertTrue(weakHashtable.contains(new Long(300)));
68          assertFalse(weakHashtable.contains(new Long(400)));
69      }
70      
71      /** Tests public boolean containsKey(Object key) */
72      public void testContainsKey() throws Exception {
73          assertTrue(weakHashtable.containsKey(new Long(1)));
74          assertTrue(weakHashtable.containsKey(new Long(2)));
75          assertTrue(weakHashtable.containsKey(new Long(3)));
76          assertFalse(weakHashtable.containsKey(new Long(100)));
77          assertFalse(weakHashtable.containsKey(new Long(200)));
78          assertFalse(weakHashtable.containsKey(new Long(300)));
79          assertFalse(weakHashtable.containsKey(new Long(400)));    
80      }
81      
82      /** Tests public boolean containsValue(Object value) */
83      public void testContainsValue() throws Exception {
84          assertFalse(weakHashtable.containsValue(new Long(1)));
85          assertFalse(weakHashtable.containsValue(new Long(2)));
86          assertFalse(weakHashtable.containsValue(new Long(3)));
87          assertTrue(weakHashtable.containsValue(new Long(100)));
88          assertTrue(weakHashtable.containsValue(new Long(200)));
89          assertTrue(weakHashtable.containsValue(new Long(300)));
90          assertFalse(weakHashtable.containsValue(new Long(400)));    
91      }
92      
93      /** Tests public Enumeration elements() */
94      public void testElements() throws Exception {
95          ArrayList elements = new ArrayList();
96          for (Enumeration e = weakHashtable.elements(); e.hasMoreElements();) {
97              elements.add(e.nextElement());
98          }
99          assertEquals(3, elements.size());
100         assertTrue(elements.contains(valueOne));
101         assertTrue(elements.contains(valueTwo));
102         assertTrue(elements.contains(valueThree));
103     }
104     
105     /** Tests public Set entrySet() */
106     public void testEntrySet() throws Exception {
107         Set entrySet = weakHashtable.entrySet();
108         for (Iterator it = entrySet.iterator(); it.hasNext();) {
109             Map.Entry entry = (Map.Entry) it.next();
110             Object key = entry.getKey();
111             if (keyOne.equals(key)) {
112                 assertEquals(valueOne, entry.getValue());
113             } else if (keyTwo.equals(key)) {
114                 assertEquals(valueTwo, entry.getValue());
115             } else if (keyThree.equals(key)) {
116                 assertEquals(valueThree, entry.getValue());
117             } else {
118                 fail("Unexpected key");
119             }
120         }
121     }
122     
123     /** Tests public Object get(Object�key) */
124     public void testGet() throws Exception {
125         assertEquals(valueOne, weakHashtable.get(keyOne));
126         assertEquals(valueTwo, weakHashtable.get(keyTwo));
127         assertEquals(valueThree, weakHashtable.get(keyThree));
128         assertNull(weakHashtable.get(new Long(50)));
129     }
130     
131     /** Tests public Enumeration keys() */
132     public void testKeys() throws Exception {
133         ArrayList keys = new ArrayList();
134         for (Enumeration e = weakHashtable.keys(); e.hasMoreElements();) {
135             keys.add(e.nextElement());
136         }
137         assertEquals(3, keys.size());
138         assertTrue(keys.contains(keyOne));
139         assertTrue(keys.contains(keyTwo));
140         assertTrue(keys.contains(keyThree));    
141     }
142     
143     /** Tests public Set keySet() */
144     public void testKeySet() throws Exception {
145         Set keySet = weakHashtable.keySet();
146         assertEquals(3, keySet.size());
147         assertTrue(keySet.contains(keyOne));
148         assertTrue(keySet.contains(keyTwo));
149         assertTrue(keySet.contains(keyThree));
150     }
151     
152     /** Tests public Object put(Object key, Object value) */
153     public void testPut() throws Exception {
154         Long anotherKey = new Long(2004);
155         weakHashtable.put(anotherKey, new Long(1066));
156         
157         assertEquals(new Long(1066), weakHashtable.get(anotherKey));
158                
159         // Test compliance with the hashtable API re nulls
160         Exception caught = null;
161         try {
162             weakHashtable.put(null, new Object());
163         }
164         catch (Exception e) {
165             caught = e;
166         }
167         assertNotNull("did not throw an exception adding a null key", caught);
168         caught = null;
169         try {
170             weakHashtable.put(new Object(), null);
171         }
172         catch (Exception e) {
173             caught = e;
174         }
175         assertNotNull("did not throw an exception adding a null value", caught);
176     }
177     
178     /** Tests public void putAll(Map t) */
179     public void testPutAll() throws Exception {
180         Map newValues = new HashMap();
181         Long newKey = new Long(1066);
182         Long newValue = new Long(1415);
183         newValues.put(newKey, newValue);
184         Long anotherNewKey = new Long(1645);
185         Long anotherNewValue = new Long(1815);
186         newValues.put(anotherNewKey, anotherNewValue);
187         weakHashtable.putAll(newValues);
188         
189         assertEquals(5, weakHashtable.size());
190         assertEquals(newValue, weakHashtable.get(newKey));
191         assertEquals(anotherNewValue, weakHashtable.get(anotherNewKey));
192     }
193     
194     /** Tests public Object remove(Object�key) */
195     public void testRemove() throws Exception {
196         weakHashtable.remove(keyOne);
197         assertEquals(2, weakHashtable.size());
198         assertNull(weakHashtable.get(keyOne));
199     }
200     
201     /** Tests public Collection values() */
202     public void testValues() throws Exception {
203         Collection values = weakHashtable.values();
204         assertEquals(3, values.size());
205         assertTrue(values.contains(valueOne));
206         assertTrue(values.contains(valueTwo));
207         assertTrue(values.contains(valueThree));
208     }
209     
210     public void testRelease() throws Exception {
211         assertNotNull(weakHashtable.get(new Long(1)));
212         ReferenceQueue testQueue = new ReferenceQueue();
213         WeakReference weakKeyOne = new WeakReference(keyOne, testQueue);
214 
215         // lose our references
216         keyOne = null;
217         keyTwo = null;
218         keyThree = null;
219         valueOne = null;
220         valueTwo = null;
221         valueThree = null;
222         
223         int iterations = 0;
224         int bytz = 2;
225         while(true) {
226             System.gc();
227             if(iterations++ > MAX_GC_ITERATIONS){
228                 fail("Max iterations reached before resource released.");
229             }
230             
231             if(weakHashtable.get(new Long(1)) == null) {
232                 break;
233                 
234             } else {
235                 // create garbage:
236                 byte[] b =  new byte[bytz];
237                 bytz = bytz * 2;
238             }
239         }
240         
241         // some JVMs seem to take a little time to put references on 
242         // the reference queue once the reference has been collected
243         // need to think about whether this is enough to justify
244         // stepping through the collection each time...
245         while(testQueue.poll() == null) {}
246         
247         // Test that the released objects are not taking space in the table
248         assertEquals("underlying table not emptied", 0, weakHashtable.size());
249     }
250 }