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