package org.oddjob.jobs.structural; import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Properties; import junit.framework.TestCase; import org.apache.log4j.Logger; import org.oddjob.FailedToStopException; import org.oddjob.Oddjob; import org.oddjob.OddjobLookup; import org.oddjob.Resetable; import org.oddjob.Stateful; import org.oddjob.arooa.convert.ArooaConversionException; import org.oddjob.arooa.reflect.ArooaPropertyException; import org.oddjob.arooa.xml.XMLConfiguration; import org.oddjob.framework.Service; import org.oddjob.state.JobState; import org.oddjob.state.ParentState; import org.oddjob.state.ServiceState; import org.oddjob.state.State; import org.oddjob.state.StateEvent; import org.oddjob.state.StateListener; import org.oddjob.tools.ConsoleCapture; import org.oddjob.tools.StateSteps; public class ServiceManagerTest extends TestCase { private static final Logger logger = Logger.getLogger(ServiceManagerTest.class); public static class Lights implements Service { volatile String are = "off"; volatile long startupTime = 10; @Override public void start() throws Exception { Thread.sleep(startupTime); are = "on"; } @Override public void stop() throws FailedToStopException { are = "off"; } public String getAre() { return are; } public void setStartupTime(long startupTime) { this.startupTime = startupTime; } @Override public String toString() { return "Light Service"; } } public static class MachineThatGoes implements Service { volatile String goes; volatile String reallyGoes; volatile long startupTime = 20; @Override public void start() throws Exception { // Try to mess up threading a bit. Thread.sleep(startupTime); reallyGoes = goes; } @Override public void stop() throws FailedToStopException { goes = "nothing"; } public void setGoes(String goes) { this.goes = goes; } public String getGoes() { return reallyGoes; } public void setStartupTime(long startupTime) { this.startupTime = startupTime; } @Override public String toString() { return "The Machine"; } } public static class MachineThatBreaks implements Service { @Override public void start() throws Exception { throw new UnsupportedOperationException( "This machine will never work!"); } @Override public void stop() throws FailedToStopException { } @Override public String toString() { return "Broken Machine"; } } @Override protected void setUp() throws Exception { super.setUp(); logger.info("------------------- " + getName() + " -------------------"); } public void testExample() throws FailedToStopException, ArooaPropertyException, ArooaConversionException { Oddjob oddjob = new Oddjob(); oddjob.setConfiguration(new XMLConfiguration( "org/oddjob/jobs/structural/ServiceManagerExample.xml", getClass().getClassLoader())); StateSteps steps = new StateSteps(oddjob); steps.startCheck(ParentState.READY, ParentState.EXECUTING, ParentState.COMPLETE); ConsoleCapture console = new ConsoleCapture(); try (ConsoleCapture.Close close = console.captureConsole()) { oddjob.run(); } steps.checkNow(); console.dump(logger); String[] lines = console.getLines(); assertEquals(1, lines.length); assertEquals("The lights are on and the machine goes ping.", lines[0].trim()); OddjobLookup lookup = new OddjobLookup(oddjob); SequentialJob test = lookup.lookup("service-manager", SequentialJob.class); Object lights = lookup.lookup("lights"); Object machine = lookup.lookup("machine"); StateEvent testState = test.lastStateEvent(); assertEquals(ParentState.COMPLETE, testState.getState()); StateSteps lightsState = new StateSteps((Stateful) lights); lightsState.startCheck(ServiceState.STARTED, ServiceState.STOPPED); StateSteps machineState = new StateSteps((Stateful) machine); machineState.startCheck(ServiceState.STARTED, ServiceState.STOPPED); oddjob.stop(); lightsState.checkNow(); machineState.checkNow(); assertEquals(testState, test.lastStateEvent()); lightsState.startCheck(ServiceState.STOPPED, ServiceState.STARTABLE); // Hard Reset a service makes no difference. ((Resetable) lights).hardReset(); lightsState.checkNow(); assertEquals(ParentState.READY, test.lastStateEvent().getState()); lightsState.startCheck(ServiceState.STARTABLE, ServiceState.STARTING, ServiceState.STARTED); ((Runnable) lights).run(); lightsState.checkNow(); assertEquals(ParentState.COMPLETE, test.lastStateEvent().getState()); oddjob.destroy(); } public void testException() throws ArooaPropertyException, ArooaConversionException { Oddjob oddjob = new Oddjob(); oddjob.setConfiguration(new XMLConfiguration( "org/oddjob/jobs/structural/ServiceManagerBroken.xml", getClass().getClassLoader())); StateSteps oddjobStates = new StateSteps(oddjob); oddjobStates.startCheck(ParentState.READY, ParentState.EXECUTING, ParentState.EXCEPTION); oddjob.load(); OddjobLookup lookup = new OddjobLookup(oddjob); SequentialJob test = lookup.lookup("service-manager", SequentialJob.class); StateSteps testStates = new StateSteps(test); testStates.startCheck(ParentState.READY, ParentState.EXECUTING, ParentState.EXCEPTION); Stateful echo = lookup.lookup("echo", Stateful.class); StateSteps echoStates = new StateSteps(echo); echoStates.startCheck(JobState.READY); oddjob.run(); oddjobStates.checkNow(); testStates.checkNow(); Object lights = lookup.lookup("lights"); Object machine = lookup.lookup("machine"); StateEvent lightsState = ((Stateful) lights).lastStateEvent(); assertEquals(ServiceState.STARTED, lightsState.getState()); StateSteps machineStates = new StateSteps((Stateful) machine); machineStates.startCheck(ServiceState.EXCEPTION, ServiceState.STARTABLE, ServiceState.STARTING, ServiceState.EXCEPTION); testStates.startCheck(ParentState.EXCEPTION, ParentState.READY, ParentState.EXECUTING, ParentState.EXCEPTION); ((Resetable) machine).softReset(); test.run(); machineStates.checkNow(); testStates.checkNow(); echoStates.checkNow(); oddjob.destroy(); } public void testOneJob() throws ArooaPropertyException, ArooaConversionException, FailedToStopException { File file = new File(getClass().getResource( "ServiceManagerOneJob.xml").getFile()); Oddjob oddjob = new Oddjob(); oddjob.setFile(file); StateSteps steps = new StateSteps(oddjob); steps.startCheck(ParentState.READY, ParentState.EXECUTING, ParentState.COMPLETE); oddjob.load(); OddjobLookup lookup = new OddjobLookup(oddjob); SequentialJob test = lookup.lookup("service-manager", SequentialJob.class); StateSteps testState = new StateSteps(test); testState.startCheck(ParentState.READY, ParentState.EXECUTING, ParentState.COMPLETE); oddjob.run(); steps.checkNow(); testState.checkNow(); Object lights = lookup.lookup("lights"); assertEquals(ServiceState.STARTED, ((Stateful) lights).lastStateEvent().getState()); testState.startCheck(ParentState.COMPLETE, ParentState.READY); test.stop(); assertEquals(ServiceState.STOPPED, ((Stateful) lights).lastStateEvent().getState()); ((Resetable) lights).hardReset(); assertEquals(ServiceState.STARTABLE, ((Stateful) lights).lastStateEvent().getState()); testState.checkNow(); testState.startCheck(ParentState.READY, ParentState.EXECUTING, ParentState.COMPLETE); test.run(); assertEquals(ServiceState.STARTED, ((Stateful) lights).lastStateEvent().getState()); testState.checkNow(); oddjob.destroy(); } public void testParallelExample() throws FailedToStopException, ArooaPropertyException, ArooaConversionException, InterruptedException { File file = new File(getClass().getResource( "ServiceManagerParallel.xml").getFile()); Properties props = new Properties(); props.setProperty("lights.startup.time", "10"); props.setProperty("machine.startup.time", "5"); Oddjob oddjob = new Oddjob(); oddjob.setFile(file); oddjob.setProperties(props); StateSteps oddjobStates = new StateSteps(oddjob); oddjobStates.startCheck(ParentState.READY, ParentState.EXECUTING, ParentState.ACTIVE, ParentState.COMPLETE); logger.info("* Starting console capture"); ConsoleCapture console = new ConsoleCapture(); try (ConsoleCapture.Close close = console.captureConsole()) { oddjob.run(); oddjobStates.checkWait(); } logger.info("* Finished console capture"); console.dump(logger); String[] lines = console.getLines(); assertEquals(1, lines.length); assertEquals("The lights are on and the machine goes ping.", lines[0].trim()); OddjobLookup lookup = new OddjobLookup(oddjob); Stateful test = lookup.lookup("service-manager", Stateful.class); Object lights = lookup.lookup("lights"); Object machine = lookup.lookup("machine"); StateEvent testState = test.lastStateEvent(); assertEquals(ParentState.COMPLETE, testState.getState()); StateSteps lightsState = new StateSteps((Stateful) lights); lightsState.startCheck(ServiceState.STARTED, ServiceState.STOPPED); StateSteps machineState = new StateSteps((Stateful) machine); machineState.startCheck(ServiceState.STARTED, ServiceState.STOPPED); oddjob.stop(); lightsState.checkNow(); machineState.checkNow(); assertEquals(testState, test.lastStateEvent()); lightsState.startCheck(ServiceState.STOPPED, ServiceState.STARTABLE); ((Resetable) lights).hardReset(); lightsState.checkNow(); assertEquals(ParentState.READY, test.lastStateEvent().getState()); lightsState.startCheck(ServiceState.STARTABLE, ServiceState.STARTING, ServiceState.STARTED); ((Runnable) lights).run(); lightsState.checkNow(); assertEquals(ParentState.COMPLETE, test.lastStateEvent().getState()); oddjob.destroy(); } public void testMultiParallelExample() throws FailedToStopException, ArooaPropertyException, ArooaConversionException, InterruptedException { File file = new File(getClass().getResource( "ServiceManagerMultiParallel.xml").getFile()); Properties props = new Properties(); props.setProperty("lights.startup.time1", "10"); props.setProperty("machine.startup.time1", "5"); props.setProperty("lights.startup.time2", "2"); props.setProperty("machine.startup.time2", "3"); Oddjob oddjob = new Oddjob(); oddjob.setFile(file); oddjob.setProperties(props); StateSteps oddjobStates = new StateSteps(oddjob); oddjobStates.startCheck(ParentState.READY, ParentState.EXECUTING, ParentState.ACTIVE, ParentState.COMPLETE); ConsoleCapture console = new ConsoleCapture(); try (ConsoleCapture.Close close = console.captureConsole()) { oddjob.run(); oddjobStates.checkWait(); } console.dump(logger); String[] lines = console.getLines(); assertEquals(1, lines.length); assertEquals("The lights are on and on, and the machines go ping and ping.", lines[0].trim()); OddjobLookup lookup = new OddjobLookup(oddjob); Stateful test = lookup.lookup("service-manager", Stateful.class); Object lights = lookup.lookup("lights1"); Object machine = lookup.lookup("machine1"); StateEvent testState = test.lastStateEvent(); assertEquals(ParentState.COMPLETE, testState.getState()); StateSteps lightsState = new StateSteps((Stateful) lights); lightsState.startCheck(ServiceState.STARTED, ServiceState.STOPPED); StateSteps machineState = new StateSteps((Stateful) machine); machineState.startCheck(ServiceState.STARTED, ServiceState.STOPPED); oddjob.stop(); lightsState.checkNow(); machineState.checkNow(); assertEquals(testState, test.lastStateEvent()); lightsState.startCheck(ServiceState.STOPPED, ServiceState.STARTABLE); ((Resetable) lights).hardReset(); lightsState.checkNow(); assertEquals(ParentState.READY, test.lastStateEvent().getState()); lightsState.startCheck(ServiceState.STARTABLE, ServiceState.STARTING, ServiceState.STARTED); ((Runnable) lights).run(); lightsState.checkNow(); assertEquals(ParentState.COMPLETE, test.lastStateEvent().getState()); oddjob.destroy(); } public void testMultiParallelExample2() throws FailedToStopException, ArooaPropertyException, ArooaConversionException, InterruptedException { File file = new File(getClass().getResource( "ServiceManagerMultiParallel2.xml").getFile()); Properties props = new Properties(); props.setProperty("lights.startup.time1", "10"); props.setProperty("machine.startup.time1", "5"); props.setProperty("lights.startup.time2", "2"); props.setProperty("machine.startup.time2", "3"); Oddjob oddjob = new Oddjob(); oddjob.setFile(file); oddjob.setProperties(props); StateSteps oddjobStates = new StateSteps(oddjob); oddjobStates.startCheck(ParentState.READY, ParentState.EXECUTING, ParentState.ACTIVE, ParentState.COMPLETE); ConsoleCapture console = new ConsoleCapture(); try (ConsoleCapture.Close close = console.captureConsole()) { oddjob.run(); oddjobStates.checkWait(); } console.dump(logger); String[] lines = console.getLines(); assertEquals(1, lines.length); assertEquals("The lights are on and on, and the machines go ping and ping.", lines[0].trim()); OddjobLookup lookup = new OddjobLookup(oddjob); Stateful test = lookup.lookup("service-manager", Stateful.class); Object lights = lookup.lookup("lights1"); Object machine = lookup.lookup("machine1"); StateEvent testState = test.lastStateEvent(); assertEquals(ParentState.COMPLETE, testState.getState()); StateSteps lightsState = new StateSteps((Stateful) lights); lightsState.startCheck(ServiceState.STARTED, ServiceState.STOPPED); StateSteps machineState = new StateSteps((Stateful) machine); machineState.startCheck(ServiceState.STARTED, ServiceState.STOPPED); oddjob.stop(); lightsState.checkNow(); machineState.checkNow(); assertEquals(testState, test.lastStateEvent()); lightsState.startCheck(ServiceState.STOPPED, ServiceState.STARTABLE); ((Resetable) lights).hardReset(); lightsState.checkNow(); assertEquals(ParentState.READY, test.lastStateEvent().getState()); lightsState.startCheck(ServiceState.STARTABLE, ServiceState.STARTING, ServiceState.STARTED); ((Runnable) lights).run(); lightsState.checkNow(); assertEquals(ParentState.COMPLETE, test.lastStateEvent().getState()); oddjob.destroy(); } public void testTimersExample() throws FailedToStopException, ArooaPropertyException, ArooaConversionException, InterruptedException { final List<Object> capture = new ArrayList<>(); class L implements StateListener { @Override public void jobStateChange(StateEvent event) { State state = event.getState(); if (state.isExecuting() || state.isComplete()) { capture.add(event.getSource()); } } } File file = new File(getClass().getResource( "ServiceManagerTimers.xml").getFile()); Oddjob oddjob = new Oddjob(); oddjob.setFile(file); oddjob.load(); OddjobLookup lookup = new OddjobLookup(oddjob); lookup.lookup("parallel", Stateful.class).addStateListener(new L()); lookup.lookup("sequential", Stateful.class).addStateListener(new L()); lookup.lookup("echo", Stateful.class).addStateListener(new L()); StateSteps oddjobStates = new StateSteps(oddjob); oddjobStates.startCheck(ParentState.READY, ParentState.EXECUTING, ParentState.ACTIVE, ParentState.COMPLETE); oddjob.run(); oddjobStates.checkWait(); assertEquals(6, capture.size()); assertEquals(ParallelJob.class, capture.get(0).getClass()); assertEquals(ParallelJob.class, capture.get(1).getClass()); assertEquals(SequentialJob.class, capture.get(2).getClass()); assertEquals(SequentialJob.class, capture.get(3).getClass()); assertEquals("Echo", capture.get(4).toString()); assertEquals("Echo", capture.get(5).toString()); oddjob.destroy(); } }