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.util.ArrayList;
019: import java.util.HashMap;
020: import java.util.Iterator;
021: import java.util.Map;
022: import java.util.Set;
023:
024: import junit.framework.Test;
025:
026: /**
027: * Tests LRUMap.
028: *
029: * @version $Revision: 155406 $ $Date: 2005-02-26 12:55:26 +0000 (Sat, 26 Feb 2005) $
030: *
031: * @author James Strachan
032: * @author Morgan Delagrange
033: * @author Stephen Colebourne
034: */
035: public class TestLRUMap extends TestSequencedHashMap {
036:
037: public TestLRUMap(String testName) {
038: super (testName);
039: }
040:
041: public static Test suite() {
042: return BulkTest.makeSuite(TestLRUMap.class);
043: }
044:
045: public static void main(String args[]) {
046: String[] testCaseName = { TestLRUMap.class.getName() };
047: junit.textui.TestRunner.main(testCaseName);
048: }
049:
050: //-----------------------------------------------------------------------
051: public Map makeEmptyMap() {
052: LRUMap map = new LRUMap();
053: return map;
054: }
055:
056: /**
057: * Override as test uses iterator() and getKey() in combination which doesn't work.
058: */
059: public String[] ignoredTests() {
060: return new String[] { "TestLRUMap.bulkTestMapEntrySet.testMapEntrySetIteratorEntry" };
061: }
062:
063: //-----------------------------------------------------------------------
064: public void testRemoveLRU() {
065: LRUMap map2 = new LRUMap(3);
066: map2.put(new Integer(1), "foo");
067: map2.put(new Integer(2), "foo");
068: map2.put(new Integer(3), "foo");
069: map2.put(new Integer(4), "foo"); // removes 1 since max size exceeded
070: map2.removeLRU(); // should be Integer(2)
071:
072: assertTrue("Second to last value should exist", map2.get(
073: new Integer(3)).equals("foo"));
074: assertTrue("First value inserted should not exist", map2
075: .get(new Integer(1)) == null);
076: }
077:
078: public void testMultiplePuts() {
079: LRUMap map2 = new LRUMap(2);
080: map2.put(new Integer(1), "foo");
081: map2.put(new Integer(2), "bar");
082: map2.put(new Integer(3), "foo");
083: map2.put(new Integer(4), "bar");
084:
085: assertTrue("last value should exist", map2.get(new Integer(4))
086: .equals("bar"));
087: assertTrue("LRU should not exist",
088: map2.get(new Integer(1)) == null);
089: }
090:
091: /**
092: * Confirm that putAll(Map) does not cause the LRUMap
093: * to exceed its maxiumum size.
094: */
095: public void testPutAll() {
096: LRUMap map2 = new LRUMap(3);
097: map2.put(new Integer(1), "foo");
098: map2.put(new Integer(2), "foo");
099: map2.put(new Integer(3), "foo");
100:
101: HashMap hashMap = new HashMap();
102: hashMap.put(new Integer(4), "foo");
103:
104: map2.putAll(hashMap);
105:
106: assertTrue("max size is 3, but actual size is " + map2.size(),
107: map2.size() == 3);
108: assertTrue("map should contain the Integer(4) object", map2
109: .containsKey(new Integer(4)));
110: }
111:
112: /**
113: * Test that the size of the map is reduced immediately
114: * when setMaximumSize(int) is called
115: */
116: public void testSetMaximumSize() {
117: LRUMap map = new LRUMap(6);
118: map.put("1", "1");
119: map.put("2", "2");
120: map.put("3", "3");
121: map.put("4", "4");
122: map.put("5", "5");
123: map.put("6", "6");
124: map.setMaximumSize(3);
125:
126: assertTrue("map should have size = 3, but actually = "
127: + map.size(), map.size() == 3);
128: }
129:
130: public void testGetPromotion() {
131: LRUMap map = new LRUMap(3);
132: map.put("1", "1");
133: map.put("2", "2");
134: map.put("3", "3");
135: // LRU is now 1 (then 2 then 3)
136:
137: // promote 1 to top
138: // eviction order is now 2,3,1
139: map.get("1");
140:
141: // add another value, forcing a remove
142: // 2 should be evicted (then 3,1,4)
143: map.put("4", "4");
144:
145: Iterator keyIterator = map.keySet().iterator();
146: Object[] keys = new Object[3];
147: for (int i = 0; keyIterator.hasNext(); ++i) {
148: keys[i] = keyIterator.next();
149: }
150:
151: assertTrue("first evicted should be 3, was " + keys[0], keys[0]
152: .equals("3"));
153: assertTrue("second evicted should be 1, was " + keys[1],
154: keys[1].equals("1"));
155: assertTrue("third evicted should be 4, was " + keys[2], keys[2]
156: .equals("4"));
157:
158: }
159:
160: /**
161: * You should be able to subclass LRUMap and perform a
162: * custom action when items are removed automatically
163: * by the LRU algorithm (the removeLRU() method).
164: */
165: public void testLRUSubclass() {
166: LRUCounter counter = new LRUCounter(3);
167: // oldest <--> newest
168: // 1
169: counter.put("1", "foo");
170: // 1 2
171: counter.put("2", "foo");
172: // 1 2 3
173: counter.put("3", "foo");
174: // 2 3 1
175: counter.put("1", "foo");
176: // 3 1 4 (2 goes out)
177: counter.put("4", "foo");
178: // 1 4 5 (3 goes out)
179: counter.put("5", "foo");
180: // 4 5 2 (1 goes out)
181: counter.put("2", "foo");
182: // 4 2
183: counter.remove("5");
184:
185: assertTrue("size should be 2, but was " + counter.size(),
186: counter.size() == 2);
187: assertTrue("removedCount should be 3 but was "
188: + counter.removedCount, counter.removedCount == 3);
189:
190: assertTrue("first removed was '2'", counter.list.get(0).equals(
191: "2"));
192: assertTrue("second removed was '3'", counter.list.get(1)
193: .equals("3"));
194: assertTrue("third removed was '1'", counter.list.get(2).equals(
195: "1"));
196:
197: assertTrue("oldest key is '4'", counter.get(0).equals("4"));
198: assertTrue("newest key is '2'", counter.get(1).equals("2"));
199: }
200:
201: protected void entrySetEqualsMap(Set set, Map m) {
202: // Overridden because LRUMap.get(Object) actually alters the map,
203: // so there's no way to verify that the entry set and map contain
204: // the same entries
205: }
206:
207: private class LRUCounter extends LRUMap {
208: int removedCount = 0;
209: ArrayList list = new ArrayList(3);
210:
211: LRUCounter(int i) {
212: super (i);
213: }
214:
215: protected void processRemovedLRU(Object key, Object value) {
216: ++removedCount;
217: list.add(key);
218: }
219: }
220:
221: }
|