package org.oddjob.framework; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import junit.framework.TestCase; import org.apache.log4j.Logger; import org.oddjob.arooa.ArooaSession; import org.oddjob.arooa.MockArooaSession; import org.oddjob.arooa.life.ComponentPersistException; import org.oddjob.arooa.parsing.MockArooaContext; import org.oddjob.arooa.registry.ComponentPool; import org.oddjob.arooa.registry.MockComponentPool; import org.oddjob.arooa.runtime.MockRuntimeConfiguration; import org.oddjob.arooa.runtime.RuntimeConfiguration; import org.oddjob.arooa.runtime.RuntimeListener; import org.oddjob.images.IconHelper; import org.oddjob.images.StateIcons; import org.oddjob.persist.Persistable; import org.oddjob.state.IsAnyState; import org.oddjob.state.JobState; import org.oddjob.state.JobStateChanger; import org.oddjob.state.JobStateHandler; import org.oddjob.state.StateListener; import org.oddjob.state.State; import org.oddjob.state.StateChanger; import org.oddjob.state.StateEvent; import org.oddjob.state.StateHandler; import org.oddjob.tools.OddjobTestHelper; public class BaseComponentTest extends TestCase { private static final Logger logger = Logger.getLogger(BaseComponentTest.class); private class OurComponent extends BaseComponent { private final JobStateHandler stateHandler = new JobStateHandler(this); private final IconHelper iconHelper = new IconHelper(this, StateIcons.iconFor(stateHandler.getState())); private final JobStateChanger stateChanger; protected OurComponent() { stateChanger = new JobStateChanger(stateHandler, iconHelper, new Persistable() { @Override public void persist() throws ComponentPersistException { save(); } }); } @Override protected StateHandler<?> stateHandler() { return stateHandler; } @Override protected IconHelper iconHelper() { return iconHelper; } protected StateChanger<JobState> getStateChanger() { return stateChanger; } @Override protected Logger logger() { return logger; } @Override protected void save() throws ComponentPersistException { OurComponent.this.save(OurComponent.this); } void complete() { stateHandler.waitToWhen(new IsAnyState(), new Runnable() { public void run() { getStateChanger().setState(JobState.COMPLETE); } }); } @Override protected void fireDestroyedState() { throw new RuntimeException("Unexpected"); } } class OurSession extends MockArooaSession { @Override public ComponentPool getComponentPool() { return new MockComponentPool() { @Override public void save(Object component) throws ComponentPersistException { throw new ComponentPersistException("Deliberate fail."); } }; } } public void testExceptionOnSave() { final OurComponent test = new OurComponent(); test.setArooaSession(new OurSession()); test.complete(); assertEquals(JobState.EXCEPTION, test.lastStateEvent().getState()); assertEquals(ComponentPersistException.class, test.lastStateEvent().getException().getClass()); } private static class SerializableComponent extends BaseComponent implements Serializable { private static final long serialVersionUID = 2010042700L; transient JobStateHandler stateHandler; transient IconHelper iconHelper; public SerializableComponent() { completeConstruction(); } private void completeConstruction() { stateHandler = new JobStateHandler(this); iconHelper = new IconHelper(this, StateIcons.iconFor(stateHandler.getState())); } @Override protected StateHandler<?> stateHandler() { return stateHandler; } @Override protected IconHelper iconHelper() { return iconHelper; } @Override protected Logger logger() { return logger; } @Override protected void save() throws ComponentPersistException { } /** * Custom serialisation. */ private void writeObject(ObjectOutputStream s) throws IOException { s.defaultWriteObject(); s.writeObject(stateHandler.lastStateEvent().serializable()); } /** * Custom serialisation. */ private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); StateEvent.SerializableNoSource savedEvent = (StateEvent.SerializableNoSource) s.readObject(); completeConstruction(); assertNotNull(iconHelper); stateHandler.restoreLastJobStateEvent(savedEvent); iconHelper.changeIcon( StateIcons.iconFor(stateHandler.getState())); } @Override protected void fireDestroyedState() { throw new RuntimeException("Unexpected."); } } public void testSerialisation() throws IOException, ClassNotFoundException, InterruptedException { SerializableComponent test = new SerializableComponent(); assertNotNull(test.stateHandler); StateEvent event = test.stateHandler.lastStateEvent(); Thread.sleep(1L); SerializableComponent copy = OddjobTestHelper.copy(test); assertNotNull(copy.stateHandler); assertEquals(event.getTime(), copy.stateHandler.lastStateEvent().getTime()); } private class OurContext extends MockArooaContext { RuntimeListener listener; @Override public RuntimeConfiguration getRuntime() { return new MockRuntimeConfiguration() { @Override public void addRuntimeListener(RuntimeListener listener) { assertNull(OurContext.this.listener); assertNotNull(listener); OurContext.this.listener = listener; } @Override public void removeRuntimeListener(RuntimeListener listener) { // TODO Auto-generated method stub super.removeRuntimeListener(listener); } }; } @Override public ArooaSession getSession() { return new MockArooaSession(); } } /** Note this test should change classes as it test the BasePrimary. */ public void testStateNotifiedOnDestroy() { final List<State> results = new ArrayList<State>(); final AtomicBoolean destroyed = new AtomicBoolean(); BasePrimary test = new BasePrimary() { JobStateHandler stateHandler = new JobStateHandler(this); IconHelper iconHelper = new IconHelper(this, StateIcons.iconFor(stateHandler.getState())); @Override protected StateHandler<?> stateHandler() { return stateHandler; } @Override protected IconHelper iconHelper() { return iconHelper; } @Override protected Logger logger() { return logger; } @Override public void onDestroy() { super.onDestroy(); destroyed.set(true); } @Override protected void fireDestroyedState() { if (!stateHandler().waitToWhen(new IsAnyState(), new Runnable() { public void run() { stateHandler.setState(JobState.DESTROYED); stateHandler.fireEvent(); } })) { throw new IllegalStateException("Failed set state DESTROYED"); } } }; test.addStateListener(new StateListener() { @Override public void jobStateChange(StateEvent event) { results.add(event.getState()); } }); OurContext context = new OurContext(); test.setArooaContext(context); context.listener.beforeDestroy(null); context.listener.afterDestroy(null); assertEquals(JobState.READY, results.get(0)); assertEquals(JobState.DESTROYED, results.get(1)); assertEquals(2, results.size()); assertTrue(destroyed.get()); } }