001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package com.tc.object.cache;
005:
006: import gnu.trove.TLinkable;
007:
008: import java.util.Collection;
009: import java.util.Iterator;
010:
011: import com.tc.object.ObjectID;
012: import com.tc.test.TCTestCase;
013:
014: /**
015: *
016: */
017: public class LRUEvictionPolicyTest extends TCTestCase {
018:
019: public EvictionPolicy createNewCache(int size) {
020: return new LRUEvictionPolicy(size);
021: }
022:
023: public void tests() throws Exception {
024: int cacheSize = 10;
025: EvictionPolicy slc = createNewCache(cacheSize);
026: Cacheable[] cacheables = new Cacheable[cacheSize];
027: for (int i = 0; i < cacheSize; i++) {
028: cacheables[i] = new TestCacheable(new ObjectID(i));
029: boolean evict = slc.add(cacheables[i]);
030: assertFalse(evict);
031: }
032: assertTrue(slc.add(new TestCacheable(new ObjectID(11))));
033: Collection c = slc.getRemovalCandidates(-1);
034: assertEquals(new ObjectID(0),
035: ((Cacheable) (c.iterator().next())).getObjectID());
036: removeAll(slc, c);
037:
038: slc.markReferenced(cacheables[1]);
039:
040: assertTrue(slc.add(new TestCacheable(new ObjectID(12))));
041: c = slc.getRemovalCandidates(-1);
042: assertEquals(1, c.size());
043: assertTrue(c.iterator().next() == cacheables[2]);
044:
045: slc.remove(cacheables[3]);
046:
047: slc.add(new TestCacheable(new ObjectID(13)));
048: c = slc.getRemovalCandidates(-1);
049: assertTrue(c.iterator().next() == cacheables[4]);
050:
051: slc.add(new TestCacheable(new ObjectID(14)));
052: c = slc.getRemovalCandidates(-1);
053:
054: assertEquals(1, c.size());
055: assertTrue(c.contains(cacheables[5]));
056: slc.remove(cacheables[5]);
057:
058: c = slc.getRemovalCandidates(-1);
059: assertEquals(1, c.size());
060: assertTrue(c.contains(cacheables[6]));
061: slc.remove(cacheables[6]);
062:
063: // repopulate the cache with just items from 'cachables'
064: for (int i = 0; i < cacheables.length; i++) {
065: cacheables[i] = new TestCacheable(new ObjectID(100 + i));
066: slc.add(cacheables[i]);
067: c = slc.getRemovalCandidates(-1);
068: removeAll(slc, c);
069: }
070:
071: // go through the cache again and assert that the cache is back down to the proper size and
072: // the LRU policy is still in effect.
073: for (int i = 0; i < cacheables.length; i++) {
074: slc.add(new TestCacheable(new ObjectID(200 + i)));
075: c = slc.getRemovalCandidates(-1);
076: assertEquals(1, c.size());
077: Cacheable evicted = (Cacheable) c.iterator().next();
078: assertTrue(evicted == cacheables[i]);
079: removeAll(slc, c);
080: }
081: }
082:
083: protected void removeAll(EvictionPolicy slc, Collection c) {
084: for (Iterator iter = c.iterator(); iter.hasNext();) {
085: slc.remove((Cacheable) iter.next());
086: }
087: }
088:
089: public static class TestCacheable implements Cacheable {
090: private ObjectID id;
091: private TLinkable next;
092: private TLinkable previous;
093: private int accessed = 0;
094:
095: public TestCacheable(ObjectID id) {
096: this .id = id;
097: }
098:
099: public TestCacheable(ObjectID id, int accessed) {
100: this .id = id;
101: this .accessed = accessed;
102: }
103:
104: public ObjectID getObjectID() {
105: return id;
106: }
107:
108: public void markAccessed() {
109: this .accessed++;
110: }
111:
112: public TLinkable getNext() {
113: return next;
114: }
115:
116: public TLinkable getPrevious() {
117: return previous;
118: }
119:
120: public void setNext(TLinkable next) {
121: this .next = next;
122: }
123:
124: public void setPrevious(TLinkable previous) {
125: this .previous = previous;
126: }
127:
128: public String toString() {
129: return "TestCacheable[" + id + "]";
130: }
131:
132: public void clearAccessed() {
133: this .accessed = 0;
134:
135: }
136:
137: public boolean recentlyAccessed() {
138: return (this .accessed > 0);
139: }
140:
141: public boolean canEvict() {
142: return true;
143: }
144:
145: public int accessCount(int factor) {
146: accessed = accessed / factor;
147: return accessed;
148: }
149:
150: public int accessCount() {
151: return accessed;
152: }
153: }
154: }
|