/* * (c) Rob Gordon 2005 */ package org.oddjob.framework; import java.io.IOException; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import junit.framework.TestCase; import org.apache.log4j.Logger; import org.oddjob.FailedToStopException; import org.oddjob.Stoppable; import org.oddjob.arooa.ArooaConfigurationException; 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.jobs.job.StopJob; import org.oddjob.state.FlagState; import org.oddjob.state.JobState; import org.oddjob.state.ParentState; import org.oddjob.state.StateOperator; import org.oddjob.state.AnyActiveStateOp; import org.oddjob.tools.OddjobTestHelper; import org.oddjob.tools.StateSteps; /** * */ public class StructuralJobTest extends TestCase { private static final Logger logger = Logger.getLogger(StructuralJobTest.class); @Override protected void setUp() throws Exception { super.setUp(); logger.info("------------------ " + getName() + " -----------------"); } private static class OurStructural extends StructuralJob<Runnable> { private static final long serialVersionUID = 1L; transient Runnable runnable; @Override protected StateOperator getInitialStateOp() { return new AnyActiveStateOp(); } void setJob(Runnable c) { childHelper.insertChild(0, c); } protected void execute() { if (runnable != null) { runnable.run(); } } } public void testRunComplete() { final FlagState child = new FlagState(JobState.COMPLETE); final OurStructural test = new OurStructural(); test.setJob(child); test.runnable = new Runnable() { public void run() { child.run(); assertEquals(ParentState.EXECUTING, test.lastStateEvent().getState()); } }; test.onInitialised(); test.run(); assertEquals(ParentState.COMPLETE, test.lastStateEvent().getState()); test.hardReset(); assertEquals(JobState.READY, child.lastStateEvent().getState()); assertEquals(ParentState.READY, test.lastStateEvent().getState()); } public void testRunInComplete() { final FlagState child = new FlagState(JobState.INCOMPLETE); final OurStructural test = new OurStructural(); test.setJob(child); test.runnable = new Runnable() { public void run() { child.run(); assertEquals(ParentState.EXECUTING, test.lastStateEvent().getState()); } }; test.onInitialised(); test.run(); assertEquals(ParentState.INCOMPLETE, test.lastStateEvent().getState()); child.setState(JobState.COMPLETE); child.softReset(); child.run(); assertEquals(JobState.COMPLETE, child.lastStateEvent().getState()); assertEquals(ParentState.COMPLETE, test.lastStateEvent().getState()); test.hardReset(); assertEquals(JobState.READY, child.lastStateEvent().getState()); assertEquals(ParentState.READY, test.lastStateEvent().getState()); } public void testRunStop() throws FailedToStopException, InterruptedException, ExecutionException, TimeoutException { final FlagState child = new FlagState(JobState.INCOMPLETE); final OurStructural test = new OurStructural(); test.setJob(child); final ExecutorService executor = Executors.newSingleThreadExecutor(); final StopJob stop = new StopJob(); stop.setJob(test); final AtomicReference<Future<?>> future = new AtomicReference<Future<?>>(); test.runnable = new Runnable() { public void run() { child.run(); assertEquals(ParentState.EXECUTING, test.lastStateEvent().getState()); future.set(executor.submit(stop)); } }; test.run(); future.get().get(10, TimeUnit.SECONDS); assertEquals(JobState.COMPLETE, stop.lastStateEvent().getState()); assertEquals(ParentState.INCOMPLETE, test.lastStateEvent().getState()); test.softReset(); stop.hardReset(); assertEquals(JobState.READY, child.lastStateEvent().getState()); assertEquals(ParentState.READY, test.lastStateEvent().getState()); child.setState(JobState.COMPLETE); test.run(); future.get().get(10, TimeUnit.SECONDS); assertEquals(JobState.COMPLETE, child.lastStateEvent().getState()); assertEquals(ParentState.COMPLETE, test.lastStateEvent().getState()); executor.shutdown(); } public void testJustChild() { final FlagState child = new FlagState(JobState.INCOMPLETE); child.run(); final OurStructural test = new OurStructural(); test.setJob(child); test.runnable = child; assertEquals(ParentState.READY, test.lastStateEvent().getState()); test.softReset(); assertEquals(JobState.READY, child.lastStateEvent().getState()); assertEquals(ParentState.READY, test.lastStateEvent().getState()); child.setState(JobState.COMPLETE); test.run(); assertEquals(JobState.COMPLETE, child.lastStateEvent().getState()); assertEquals(ParentState.COMPLETE, test.lastStateEvent().getState()); } public void testPersist() throws IOException, ClassNotFoundException { FlagState child = new FlagState(JobState.COMPLETE); OurStructural test = new OurStructural(); test.setJob(child); test.run(); child.run(); assertEquals(ParentState.COMPLETE, test.lastStateEvent().getState()); OurStructural copy = (OurStructural) OddjobTestHelper.copy(test); assertEquals(ParentState.COMPLETE, copy.lastStateEvent().getState()); } class OurSession extends MockArooaSession { OurStructural saved; @Override public ComponentPool getComponentPool() { return new MockComponentPool() { @Override public void configure(Object component) { } @Override public void save(Object component) { if (component instanceof OurStructural) { try { saved = (OurStructural) OddjobTestHelper.copy(component); } catch (Exception e) { throw new RuntimeException(e); } } else { throw new RuntimeException("Unexpected."); } } }; } } public void testRunCompletePersist() { OurSession session = new OurSession(); final FlagState child = new FlagState(JobState.COMPLETE); final OurStructural test = new OurStructural(); test.setArooaSession(session); test.setJob(child); test.runnable = new Runnable() { public void run() { child.run(); assertEquals(ParentState.EXECUTING, test.lastStateEvent().getState()); } }; test.onInitialised(); test.run(); assertEquals(ParentState.COMPLETE, test.lastStateEvent().getState()); OurStructural test2 = session.saved; final FlagState child2 = new FlagState(JobState.COMPLETE); test2.setArooaSession(session); test2.setJob(child2); test2.runnable = new Runnable() { public void run() { child2.run(); assertEquals(ParentState.EXECUTING, test.lastStateEvent().getState()); } }; test2.onInitialised(); assertEquals(ParentState.COMPLETE, test2.lastStateEvent().getState()); assertEquals(JobState.READY, child2.lastStateEvent().getState()); test2.hardReset(); assertEquals(JobState.READY, child2.lastStateEvent().getState()); assertEquals(ParentState.READY, test2.lastStateEvent().getState()); } 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) { super.removeRuntimeListener(listener); } }; } @Override public ArooaSession getSession() { return new MockArooaSession(); } } private class SimpleStructural extends StructuralJob<Runnable> { private static final long serialVersionUID = 2010080500L; void setChild(Runnable child) { if (child == null) { childHelper.removeChildAt(0); } else { childHelper.insertChild(0, child); } } @Override protected void execute() throws Throwable { childHelper.getChild().run(); } @Override protected StateOperator getInitialStateOp() { return new AnyActiveStateOp(); } } public void testChildDestroyed() throws FailedToStopException { SimpleJob component = new SimpleJob() { @Override protected int execute() throws Throwable { return 0; } @Override protected void save() throws ComponentPersistException { } @Override protected void configure() throws ArooaConfigurationException { } }; OurContext childContext = new OurContext(); component.setArooaContext(childContext); final SimpleStructural test = new SimpleStructural(); StateSteps state = new StateSteps(test); state.startCheck(ParentState.READY, ParentState.EXECUTING, ParentState.COMPLETE, ParentState.READY); test.setChild(component); test.run(); childContext.listener.beforeDestroy(null); test.setChild(null); childContext.listener.afterDestroy(null); state.checkNow(); } public void testBothDestroyed() throws FailedToStopException { SimpleJob component = new SimpleJob() { @Override protected int execute() throws Throwable { return 0; } @Override protected void save() throws ComponentPersistException { } @Override protected void configure() throws ArooaConfigurationException { } }; OurContext childContext = new OurContext(); component.setArooaContext(childContext); final SimpleStructural test = new SimpleStructural() { private static final long serialVersionUID = 2010092900L; @Override protected void save() throws ComponentPersistException { } protected void configure() { } }; OurContext structuralContext = new OurContext(); test.setArooaContext(structuralContext); StateSteps state = new StateSteps(test); state.startCheck(ParentState.READY, ParentState.EXECUTING, ParentState.COMPLETE); test.setChild(component); test.run(); state.checkNow(); state.startCheck(ParentState.COMPLETE, ParentState.DESTROYED); structuralContext.listener.beforeDestroy(null); childContext.listener.beforeDestroy(null); test.setChild(null); childContext.listener.afterDestroy(null); structuralContext.listener.afterDestroy(null); state.checkNow(); } private class AnyStructural extends StructuralJob<Object> { private static final long serialVersionUID = 2010080500L; void setChild(Object child) { childHelper.insertChild(0, child); } @Override protected void execute() throws Throwable { } @Override protected StateOperator getInitialStateOp() { return new AnyActiveStateOp(); } } public void testChildStopped() throws FailedToStopException { final AtomicBoolean stopped = new AtomicBoolean(); Object component = new Stoppable() { @Override public void stop() throws FailedToStopException { stopped.set(true); } }; AnyStructural test = new AnyStructural(); StateSteps check = new StateSteps(test); check.startCheck(ParentState.READY); test.setChild(component); test.stop(); assertEquals(true, stopped.get()); check.checkNow(); } }