package org.oddjob;
import java.io.File;
import java.util.concurrent.Exchanger;
import junit.framework.TestCase;
import org.apache.log4j.Logger;
import org.oddjob.arooa.xml.XMLConfiguration;
import org.oddjob.framework.SimpleJob;
import org.oddjob.io.BufferType;
import org.oddjob.jobs.ExecJob;
import org.oddjob.jobs.WaitJob;
import org.oddjob.state.JobState;
import org.oddjob.state.State;
import org.oddjob.state.StateConditions;
import org.oddjob.tools.ConsoleCapture;
import org.oddjob.tools.OurDirs;
public class MainShutdownTest extends TestCase {
private static final Logger logger = Logger.getLogger(MainTest.class);
@Override
protected void setUp() throws Exception {
logger.debug("------------------ " + getName() + " -----------------");
}
public static class OurSimpleJob extends SimpleJob
implements Stoppable {
boolean stopped;
Thread t;
Exchanger<Void> exchanger = new Exchanger<Void>();
@Override
protected synchronized int execute() throws Throwable {
t = Thread.currentThread();
exchanger.exchange(null);
try {
while (true) {
wait();
}
} catch (InterruptedException e) {
logger.debug("OurSimpleJob interrupted.");
}
return 0;
}
public synchronized void onStop() {
stopped = true;
t.interrupt();
}
}
public void testShutdownHook() throws Exception {
String xml = "<oddjob>" +
" <job>" +
" <bean id='r' class='" + OurSimpleJob.class.getName() + "'/>" +
" </job>" +
"</oddjob>";
Oddjob oddjob = new Oddjob();
oddjob.setConfiguration(new XMLConfiguration("XML", xml));
oddjob.load();
OurSimpleJob r = (OurSimpleJob) new OddjobLookup(oddjob).lookup("r");
assertNotNull(r);
Thread t = new Thread(oddjob);
t.start();
logger.info("Waiting for OurSimpleJob to be stoppable.");
r.exchanger.exchange(null);
OddjobRunner.ShutdownHook hook = new OddjobRunner(oddjob). new ShutdownHook();
hook.run();
assertTrue(r.stopped);
}
public static class NaughtyJob implements Runnable {
@Override
public void run() {
WaitJob wait = new WaitJob() {
@Override
public int execute() throws Exception {
System.out.println("Naughty Thread Started.");
return super.execute();
}
};
new Thread(wait).start();
}
}
/** This doesn't test what we'd hoped because process destroy
* appears to kill the jvm without invoking the shutdown hook.
*
* @throws FailedToStopException
* @throws InterruptedException
*/
public void testKillerThread() throws FailedToStopException, InterruptedException {
OurDirs dirs = new OurDirs();
File testClasses = dirs.relative("classes");
if (!testClasses.exists()) {
testClasses = dirs.relative("build/test");
}
if (!testClasses.exists()) {
fail ("No test classes!");
}
ExecJob exec = new ExecJob();
exec.setArgs(new String[] {
"java",
"-D" + OddjobRunner.KILLER_TIMEOUT_PROPERTY + "=1",
"-jar",
dirs.relative("run-oddjob.jar").getPath(),
"-cp",
testClasses.getPath(),
"-f",
dirs.relative(
"test/conf/test-killer.xml").getPath()
});
ConsoleCapture console = new ConsoleCapture();
try (ConsoleCapture.Close close = console.capture(exec.consoleLog())) {
new Thread(exec).start();
WaitJob wait = new WaitJob();
wait.setFor(exec);
wait.setState(StateConditions.EXECUTING);
wait.run();
while (true) {
Thread.sleep(500);
BufferType buffer = new BufferType();
buffer.setLines(console.getLines());
buffer.configured();
State jobState = exec.lastStateEvent().getState();
if (buffer.getText().contains("Naughty Thread Started.")) {
break;
}
else {
if (JobState.EXECUTING != jobState) {
console.dump(logger);
fail("Something wrong.");
}
}
logger.info("Waiting for console.");
}
exec.stop();
}
console.dump(logger);
assertEquals(1, exec.getExitValue());
assertEquals(JobState.INCOMPLETE,
exec.lastStateEvent().getState());
}
}