// Copyright (c) 2005 Dustin Sallings <dustin@spy.net> package net.spy.factory; import java.util.ArrayList; import java.util.Collection; import junit.framework.TestCase; import net.spy.cache.SimpleCache; /** * Test the generic factory code. */ public class GenFactoryImplTest extends TestCase { private static final int NUM_OBJECTS=1000; private static final String TEST_KEY = "TestStuff"; private TestFactory tf=null; @Override public void setUp() { tf=new TestFactory(); } @Override public void tearDown() { SimpleCache.setInstance(null); if(CacheRefresher.getInstance() != null) { CacheRefresher.getInstance().shutdown(); } } /** * Test the factory thingy. */ public void testFactory() throws Exception { // Try all the existing objects checkFirstPass(); // Get the thing to recache tf.recache(); checkSecondPass(); } public void testInsertion() throws Exception { tf.recache(); assertNull(tf.getObject(891885)); TestInstance ti=new TestInstance(891885); tf.cacheInstance(ti); assertNotNull(tf.getObject(891885)); } private void checkFirstPass() { for(int i=0; i<NUM_OBJECTS; i++) { TestInstance ti=tf.getObject(i); assertNotNull("Null at " + i, ti); assertEquals(ti.getId(), i); ti=tf.getObject("iprop", String.valueOf(i)); assertNotNull("Null at iprop/" + i, ti); assertEquals(ti.getId(), i); } assertEquals(NUM_OBJECTS, tf.getObjects().size()); // Try non-existing objects TestInstance ti=tf.getObject(NUM_OBJECTS + 138); assertNull(ti); ti=tf.getObject("iprop", String.valueOf(NUM_OBJECTS + 138)); assertNull("Null at iprop/" + (NUM_OBJECTS+138), ti); assertEquals(1, tf.numRuns); } private void checkSecondPass() { // Now that object should be there. TestInstance ti=tf.getObject(NUM_OBJECTS + 138); assertNotNull("Was null on second pass", ti); assertEquals(ti.getId(), NUM_OBJECTS + 138); // And this object shouldn't ti=tf.getObject(138); assertNull(ti); assertEquals(2, tf.numRuns); } /** * Test the factory thingy with delayed recaches. */ public void testFactoryDelayedRecache() throws Exception { checkFirstPass(); // Tell the thing to recache CacheRefresher cc=CacheRefresher.getInstance(); cc.recache(tf, System.currentTimeMillis(), 100); // Still should have the same stuff checkFirstPass(); // Let the stuff have time to recache. Thread.sleep(300); checkSecondPass(); } /** * Test the factory thingy with double-delayed recaches. */ public void testFactoryDoubleDelayedRecache() throws Exception { checkFirstPass(); // Tell the thing to recache CacheRefresher cc=CacheRefresher.getInstance(); cc.recache(tf, System.currentTimeMillis(), 100); // Still should have the same stuff checkFirstPass(); // Let a little time pass and then recache. Thread.sleep(50); cc.recache(tf, System.currentTimeMillis(), 100); // Let a little more time pass and then validate we haven't recached Thread.sleep(75); checkFirstPass(); // With a bit more time passed, we should be on the new set. Thread.sleep(250); checkSecondPass(); } public void testMultiFetch() throws Exception { assertEquals(0, tf.getObjects("multi", 0).size()); assertEquals(0, tf.getObjects("constant", 0).size()); assertEquals(1000, tf.getObjects("constant", 19).size()); } public void testInvalidCacheRefresherAssignment() { try { CacheRefresher cc=CacheRefresher.getInstance(); CacheRefresher.setInstance(cc); fail("Overwrite cache refresher instance"); } catch(IllegalStateException e) { assertEquals("Attempting to overwrite cache refresher instance", e.getMessage()); } } public void testInvalidConstructors() { try { TestFactory t=new TestFactory(null, 10000); fail("Shouldn't be able to construct a factory with a null name: " + t); } catch(NullPointerException e) { assertNotNull(e.getMessage()); } try { TestFactory t=new TestFactory("Test", 0); fail("Shouldn't be able to construct a factory with 0 cache time: " + t); } catch(IllegalArgumentException e) { assertNotNull(e.getMessage()); } try { TestFactory t=new TestFactory("Test", -103); fail("Shouldn't be able to construct a factory with " + "negative cache time: " + t); } catch(IllegalArgumentException e) { assertNotNull(e.getMessage()); } } public static class TestInstance extends Object { @CacheKey(name="id") private int oid=0; public TestInstance(int id) { super(); this.oid=id; } public int getId() { return(oid); } @CacheKey(name="constant", type=CacheType.MULTI) public int getConstant() { return 19; } @CacheKey(name="iprop") public String getIndexedProp() { return String.valueOf(oid); } public String getNonindexedProp() { return String.valueOf(0-oid); } @Override public int hashCode() { return(oid); } @Override public boolean equals(Object o) { boolean rv=false; if(o instanceof TestInstance) { TestInstance ti=(TestInstance)o; rv=oid == ti.oid; } return(rv); } } private static class TestFactory extends GenFactoryImpl<TestInstance> { private int lastObject=0; public int numRuns=0; public TestFactory(String nm, long t) { super(nm, t); } public TestFactory() { this(TEST_KEY, 10000); } @Override public void cacheInstance(TestInstance i) throws Exception { super.cacheInstance(i); } @Override public Collection<TestInstance> getInstances() { Collection<TestInstance> rv=new ArrayList<TestInstance>(); int startId=lastObject; for(int i=0; i<NUM_OBJECTS; i++) { int id=i + startId; rv.add(new TestInstance(id)); lastObject=id; } numRuns++; return(rv); } } }