001: /*
002: * Copyright 2001-2004 The Apache Software Foundation
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.commons.collections;
017:
018: import java.lang.ref.WeakReference;
019: import java.util.Map;
020:
021: import junit.framework.Test;
022:
023: import org.apache.commons.collections.map.AbstractTestMap;
024:
025: /**
026: * Tests for ReferenceMap.
027: *
028: * @version $Revision: 169101 $ $Date: 2005-05-07 18:26:58 +0100 (Sat, 07 May 2005) $
029: *
030: * @author Paul Jack
031: * @author Guilhem Lavaux
032: */
033: public class TestReferenceMap extends AbstractTestMap {
034:
035: public TestReferenceMap(String testName) {
036: super (testName);
037: }
038:
039: public static Test suite() {
040: return BulkTest.makeSuite(TestReferenceMap.class);
041: }
042:
043: public static void main(String args[]) {
044: String[] testCaseName = { TestReferenceMap.class.getName() };
045: junit.textui.TestRunner.main(testCaseName);
046: }
047:
048: public Map makeEmptyMap() {
049: ReferenceMap map = new ReferenceMap(ReferenceMap.WEAK,
050: ReferenceMap.WEAK);
051: return map;
052: }
053:
054: public boolean isAllowNullKey() {
055: return false;
056: }
057:
058: public boolean isAllowNullValue() {
059: return false;
060: }
061:
062: public String getCompatibilityVersion() {
063: return "2.1";
064: }
065:
066: //-----------------------------------------------------------------------
067: public void testNullHandling() {
068: resetFull();
069: assertEquals(null, map.get(null));
070: assertEquals(false, map.containsKey(null));
071: assertEquals(false, map.containsValue(null));
072: assertEquals(null, map.remove(null));
073: assertEquals(false, map.entrySet().contains(null));
074: assertEquals(false, map.keySet().contains(null));
075: assertEquals(false, map.values().contains(null));
076: try {
077: map.put(null, null);
078: fail();
079: } catch (NullPointerException ex) {
080: }
081: try {
082: map.put(new Object(), null);
083: fail();
084: } catch (NullPointerException ex) {
085: }
086: try {
087: map.put(null, new Object());
088: fail();
089: } catch (NullPointerException ex) {
090: }
091: }
092:
093: //-----------------------------------------------------------------------
094: /*
095: // Tests often fail because gc is uncontrollable
096:
097: public void testPurge() {
098: ReferenceMap map = new ReferenceMap(ReferenceMap.WEAK, ReferenceMap.WEAK);
099: Object[] hard = new Object[10];
100: for (int i = 0; i < hard.length; i++) {
101: hard[i] = new Object();
102: map.put(hard[i], new Object());
103: }
104: gc();
105: assertTrue("map should be empty after purge of weak values", map.isEmpty());
106:
107: for (int i = 0; i < hard.length; i++) {
108: map.put(new Object(), hard[i]);
109: }
110: gc();
111: assertTrue("map should be empty after purge of weak keys", map.isEmpty());
112:
113: for (int i = 0; i < hard.length; i++) {
114: map.put(new Object(), hard[i]);
115: map.put(hard[i], new Object());
116: }
117:
118: gc();
119: assertTrue("map should be empty after purge of weak keys and values", map.isEmpty());
120: }
121:
122:
123: public void testGetAfterGC() {
124: ReferenceMap map = new ReferenceMap(ReferenceMap.WEAK, ReferenceMap.WEAK);
125: for (int i = 0; i < 10; i++) {
126: map.put(new Integer(i), new Integer(i));
127: }
128:
129: gc();
130: for (int i = 0; i < 10; i++) {
131: Integer I = new Integer(i);
132: assertTrue("map.containsKey should return false for GC'd element", !map.containsKey(I));
133: assertTrue("map.get should return null for GC'd element", map.get(I) == null);
134: }
135: }
136:
137:
138: public void testEntrySetIteratorAfterGC() {
139: ReferenceMap map = new ReferenceMap(ReferenceMap.WEAK, ReferenceMap.WEAK);
140: Object[] hard = new Object[10];
141: for (int i = 0; i < 10; i++) {
142: hard[i] = new Integer(10 + i);
143: map.put(new Integer(i), new Integer(i));
144: map.put(hard[i], hard[i]);
145: }
146:
147: gc();
148: Iterator iterator = map.entrySet().iterator();
149: while (iterator.hasNext()) {
150: Map.Entry entry = (Map.Entry)iterator.next();
151: Integer key = (Integer)entry.getKey();
152: Integer value = (Integer)entry.getValue();
153: assertTrue("iterator should skip GC'd keys", key.intValue() >= 10);
154: assertTrue("iterator should skip GC'd values", value.intValue() >= 10);
155: }
156:
157: }
158: */
159:
160: WeakReference keyReference;
161: WeakReference valueReference;
162:
163: public Map buildRefMap() {
164: Object key = new Object();
165: Object value = new Object();
166:
167: keyReference = new WeakReference(key);
168: valueReference = new WeakReference(value);
169:
170: Map testMap = new ReferenceMap(ReferenceMap.WEAK,
171: ReferenceMap.HARD, true);
172: testMap.put(key, value);
173:
174: assertEquals("In map", value, testMap.get(key));
175: assertNotNull("Weak reference released early (1)", keyReference
176: .get());
177: assertNotNull("Weak reference released early (2)",
178: valueReference.get());
179: return testMap;
180: }
181:
182: /** Tests whether purge values setting works */
183: public void testPurgeValues() throws Exception {
184: // many thanks to Juozas Baliuka for suggesting this method
185:
186: Map testMap = buildRefMap();
187:
188: int iterations = 0;
189: int bytz = 2;
190: while (true) {
191: System.gc();
192: if (iterations++ > 50) {
193: fail("Max iterations reached before resource released.");
194: }
195: testMap.isEmpty();
196: if (keyReference.get() == null
197: && valueReference.get() == null) {
198: break;
199:
200: } else {
201: // create garbage:
202: byte[] b = new byte[bytz];
203: bytz = bytz * 2;
204: }
205: }
206: }
207:
208: private static void gc() {
209: try {
210: // trigger GC
211: byte[][] tooLarge = new byte[1000000000][1000000000];
212: fail("you have too much RAM");
213: } catch (OutOfMemoryError ex) {
214: System.gc(); // ignore
215: }
216: }
217: }
|