001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     * 
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     * 
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */ 
017    
018    
019    package org.apache.commons.logging.impl;
020    
021    import java.lang.ref.*;
022    import junit.framework.*;
023    import java.util.*;
024    
025    public class WeakHashtableTest extends TestCase {
026    
027        
028        /** Maximum number of iterations before our test fails */
029        private static final int MAX_GC_ITERATIONS = 50;
030    
031        private WeakHashtable weakHashtable;
032        private Long keyOne;
033        private Long keyTwo;
034        private Long keyThree;
035        private Long valueOne;
036        private Long valueTwo;
037        private Long valueThree;
038    
039        public WeakHashtableTest(String testName) {
040            super(testName);
041        }
042        
043    
044        protected void setUp() throws Exception {
045            super.setUp();
046            weakHashtable = new WeakHashtable();
047            
048            keyOne = new Long(1);
049            keyTwo = new Long(2);
050            keyThree = new Long(3);
051            valueOne = new Long(100);
052            valueTwo = new Long(200);
053            valueThree = new Long(300);
054            
055            weakHashtable.put(keyOne, valueOne);
056            weakHashtable.put(keyTwo, valueTwo);
057            weakHashtable.put(keyThree, valueThree);
058        }
059    
060        /** Tests public boolean contains(Object value) */
061        public void testContains() throws Exception {
062            assertFalse(weakHashtable.contains(new Long(1)));
063            assertFalse(weakHashtable.contains(new Long(2)));
064            assertFalse(weakHashtable.contains(new Long(3)));
065            assertTrue(weakHashtable.contains(new Long(100)));
066            assertTrue(weakHashtable.contains(new Long(200)));
067            assertTrue(weakHashtable.contains(new Long(300)));
068            assertFalse(weakHashtable.contains(new Long(400)));
069        }
070        
071        /** Tests public boolean containsKey(Object key) */
072        public void testContainsKey() throws Exception {
073            assertTrue(weakHashtable.containsKey(new Long(1)));
074            assertTrue(weakHashtable.containsKey(new Long(2)));
075            assertTrue(weakHashtable.containsKey(new Long(3)));
076            assertFalse(weakHashtable.containsKey(new Long(100)));
077            assertFalse(weakHashtable.containsKey(new Long(200)));
078            assertFalse(weakHashtable.containsKey(new Long(300)));
079            assertFalse(weakHashtable.containsKey(new Long(400)));    
080        }
081        
082        /** Tests public boolean containsValue(Object value) */
083        public void testContainsValue() throws Exception {
084            assertFalse(weakHashtable.containsValue(new Long(1)));
085            assertFalse(weakHashtable.containsValue(new Long(2)));
086            assertFalse(weakHashtable.containsValue(new Long(3)));
087            assertTrue(weakHashtable.containsValue(new Long(100)));
088            assertTrue(weakHashtable.containsValue(new Long(200)));
089            assertTrue(weakHashtable.containsValue(new Long(300)));
090            assertFalse(weakHashtable.containsValue(new Long(400)));    
091        }
092        
093        /** Tests public Enumeration elements() */
094        public void testElements() throws Exception {
095            ArrayList elements = new ArrayList();
096            for (Enumeration e = weakHashtable.elements(); e.hasMoreElements();) {
097                elements.add(e.nextElement());
098            }
099            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    }