package org.oddjob; import java.util.concurrent.atomic.AtomicReference; import junit.framework.TestCase; import org.oddjob.OddjobRunner.ExitHandler; import org.oddjob.arooa.xml.XMLConfiguration; import org.oddjob.framework.Service; import org.oddjob.framework.SimpleJob; import org.oddjob.state.JobState; import org.oddjob.state.ParentState; import org.oddjob.state.ServiceState; import org.oddjob.tools.OddjobTestHelper; import org.oddjob.tools.StateSteps; public class OddjobRunnerTest extends TestCase { String timeoutProperty; @Override protected void setUp() throws Exception { super.setUp(); timeoutProperty = System.getProperty( OddjobRunner.KILLER_TIMEOUT_PROPERTY); } @Override protected void tearDown() throws Exception { super.tearDown(); if (timeoutProperty == null) { System.getProperties().remove( OddjobRunner.KILLER_TIMEOUT_PROPERTY); } else { System.setProperty(OddjobRunner.KILLER_TIMEOUT_PROPERTY, timeoutProperty); } } public static class OurService implements Service { volatile boolean started; @Override public void start() throws Exception { if (started) { throw new IllegalStateException(); } started = true; } @Override public void stop() throws FailedToStopException { if (!started) { throw new IllegalStateException(); } started = false; } public boolean isStarted() { return started; } } public void testOddjobDestroyedFromShutdownHook() throws Exception { System.setProperty(OddjobRunner.KILLER_TIMEOUT_PROPERTY, new Long(Long.MAX_VALUE).toString()); String xml = "<oddjob>" + " <job>" + " <bean id='service' class='" + OurService.class.getName() + "'/>" + " </job>" + "</oddjob>"; Oddjob oddjob = new Oddjob(); oddjob.setConfiguration(new XMLConfiguration("TEST", xml)); oddjob.load(); Object serviceProxy = new OddjobLookup(oddjob).lookup("service"); OddjobRunner test = new OddjobRunner(oddjob, new ExitHandler() { @Override public void exit(int exitStatus) { throw new RuntimeException("Unexpected!"); } }); final StateSteps serviceStates = new StateSteps((Stateful) serviceProxy); final StateSteps oddjobStates = new StateSteps(oddjob); oddjobStates.startCheck(ParentState.READY, ParentState.EXECUTING, ParentState.STARTED); final Runnable shutdownHook = test.new ShutdownHook(); final AtomicReference<Exception> ex = new AtomicReference<>(); Thread t = new Thread(new Runnable() { @Override public void run() { try { oddjobStates.checkWait(); oddjobStates.startCheck(ParentState.STARTED, ParentState.DESTROYED); serviceStates.startCheck(ServiceState.STARTED, ServiceState.STOPPED, ServiceState.DESTROYED); shutdownHook.run(); } catch (Exception e) { ex.set(e); } } }); t.start(); test.run(); t.join(OddjobTestHelper.TEST_TIMEOUT); serviceStates.checkNow(); oddjobStates.checkNow(); if (ex.get() != null) { throw ex.get(); } } public static class FailsToDestroy extends SimpleJob { @Override protected int execute() throws Throwable { sleep(Long.MAX_VALUE); return 0; } @Override protected void onDestroy() { super.onDestroy(); try { Thread.sleep(Long.MAX_VALUE); } catch (InterruptedException e) { // Expected } } } public void testTimeoutKiller() throws Exception { System.setProperty(OddjobRunner.KILLER_TIMEOUT_PROPERTY, "1"); String xml = "<oddjob>" + " <job>" + " <bean id='slow' class='" + FailsToDestroy.class.getName() + "'/>" + " </job>" + "</oddjob>"; Oddjob oddjob = new Oddjob(); oddjob.setConfiguration(new XMLConfiguration("TEST", xml)); oddjob.load(); Object slowToDestroy = new OddjobLookup(oddjob).lookup("slow"); final AtomicReference<Thread> shutdownThread = new AtomicReference<>();; OddjobRunner test = new OddjobRunner(oddjob, new ExitHandler() { @Override public void exit(int exitStatus) { assertEquals(-1, exitStatus); shutdownThread.get().interrupt(); } }); final StateSteps slowStates = new StateSteps( (Stateful) slowToDestroy); slowStates.startCheck(JobState.READY, JobState.EXECUTING); final Runnable shutdownHook = test.new ShutdownHook(); final AtomicReference<Exception> ex = new AtomicReference<>(); Thread t = new Thread(new Runnable() { @Override public void run() { try { slowStates.checkWait(); shutdownThread.set(Thread.currentThread()); shutdownHook.run(); } catch (InterruptedException e) { ex.set(e); } } }); t.start(); test.run(); t.join(OddjobTestHelper.TEST_TIMEOUT); if (ex.get() != null) { throw ex.get(); } } }