Commit f0c6473c authored by Joerg Domaschka's avatar Joerg Domaschka

more test scripts for lifecylce handling; slight adaptation of interfaces to...

more test scripts for lifecylce handling; slight adaptation of interfaces to allow throwing of exceptions
parent e94836d5
......@@ -22,5 +22,5 @@ import java.io.Serializable;
public interface LifecycleHandler extends Serializable {
void execute(ExecutionContext ec);
void execute(ExecutionContext ec) throws LifecycleException;
}
......@@ -44,7 +44,6 @@ final class BashExecutionHelper {
}
static ExecutionResult doExecuteCommand(boolean blocking, String command, Shell shell) {
// TODO: evaluate return values of commands and throw exceptions //
if(blocking) {
return shell.executeBlockingCommand(command);
}
......
......@@ -28,15 +28,15 @@ public interface LifecycleActionInterceptor {
void prepare(HandlerType type) throws ContainerException;
void postprocess(HandlerType type);
void postprocess(HandlerType type) throws ContainerException;
ComponentInstanceId getComponentInstanceId();
void postprocessPortUpdate(PortDiff<DownstreamAddress> diff);
void postprocessPortUpdate(PortDiff<DownstreamAddress> diff) throws ContainerException;
void preprocessPortUpdate(PortDiff<DownstreamAddress> diff) throws ContainerException;
void postprocessDetector(DetectorType type);
void postprocessDetector(DetectorType type) throws ContainerException;
void preprocessDetector(DetectorType type) throws ContainerException;
}
......@@ -58,7 +58,7 @@ public final class LifecycleController {
interceptor.prepare(type);
}
private void postRun(HandlerType type) {
private void postRun(HandlerType type) throws ContainerException {
interceptor.postprocess(type);
}
......@@ -72,6 +72,7 @@ public final class LifecycleController {
LOGGER
.warn("Exception when executing state transition. this is not thoroughly handled.",
ce);
throw new IllegalStateException("wrong state: should be in error state", ce);
// set error state
// updateStateInRegistry(type);
}
......@@ -142,6 +143,7 @@ public final class LifecycleController {
LOGGER
.warn("Exception when executing state transition. this is not thoroughly handled.",
ce);
throw new IllegalStateException("wrong state: should be in error state?", ce);
// set error state
// updateStateInRegistry(LifecycleHandlerType.START);
} finally {
......
......@@ -43,7 +43,7 @@ public class LifecycleControllerTransitions {
new TransitionAction() {
@Override public void transit(Object[] params) {
InitHandler h = store.getHandler(LifecycleHandlerType.INIT, InitHandler.class);
h.execute(ec);
try { h.execute(ec); } catch(LifecycleException lce) {throw new RuntimeException(lce);}
}
});
}
......@@ -53,21 +53,21 @@ public class LifecycleControllerTransitions {
new TransitionAction() {
@Override public void transit(Object[] params) {
PreInstallHandler h = store.getHandler(LifecycleHandlerType.PRE_INSTALL, PreInstallHandler.class);
h.execute(ec);
try { h.execute(ec); } catch(LifecycleException lce) {throw new RuntimeException(lce);}
}
}).
addSynchronousTransition(LifecycleHandlerType.PRE_INSTALL, LifecycleHandlerType.INSTALL,
new TransitionAction() {
@Override public void transit(Object[] params) {
InstallHandler h = store.getHandler(LifecycleHandlerType.INSTALL, InstallHandler.class);
h.execute(ec);
try { h.execute(ec); } catch(LifecycleException lce) {throw new RuntimeException(lce);}
}
}).
addSynchronousTransition(LifecycleHandlerType.INSTALL, LifecycleHandlerType.POST_INSTALL,
new TransitionAction() {
@Override public void transit(Object[] params) {
PostInstallHandler h = store.getHandler(LifecycleHandlerType.POST_INSTALL, PostInstallHandler.class);
h.execute(ec);
try { h.execute(ec); } catch(LifecycleException lce) {throw new RuntimeException(lce);}
}
});
}
......@@ -77,21 +77,21 @@ public class LifecycleControllerTransitions {
new TransitionAction() {
@Override public void transit(Object[] params) {
PreStartHandler h = store.getHandler(LifecycleHandlerType.PRE_START, PreStartHandler.class);
h.execute(ec);
try { h.execute(ec); } catch(LifecycleException lce) {throw new RuntimeException(lce);}
}
}).
addSynchronousTransition(LifecycleHandlerType.PRE_START, LifecycleHandlerType.START,
new TransitionAction() {
@Override public void transit(Object[] params) {
StartHandler h = store.getHandler(LifecycleHandlerType.START, StartHandler.class);
h.execute(ec);
try { h.execute(ec); } catch(LifecycleException lce) {throw new RuntimeException(lce);}
}
}).
addSynchronousTransition(LifecycleHandlerType.START, LifecycleHandlerType.POST_START,
new TransitionAction() {
@Override public void transit(Object[] params) {
PostStartHandler h = store.getHandler(LifecycleHandlerType.POST_START, PostStartHandler.class);
h.execute(ec);
try { h.execute(ec); } catch(LifecycleException lce) {throw new RuntimeException(lce);}
}
});
}
......@@ -101,21 +101,21 @@ public class LifecycleControllerTransitions {
new TransitionAction() {
@Override public void transit(Object[] params) {
PreStopHandler h = store.getHandler(LifecycleHandlerType.PRE_STOP, PreStopHandler.class);
h.execute(ec);
try { h.execute(ec); } catch(LifecycleException lce) {throw new RuntimeException(lce);}
}
}).
addSynchronousTransition(LifecycleHandlerType.PRE_STOP, LifecycleHandlerType.STOP,
new TransitionAction() {
@Override public void transit(Object[] params) {
StopHandler h = store.getHandler(LifecycleHandlerType.STOP, StopHandler.class);
h.execute(ec);
try { h.execute(ec); } catch(LifecycleException lce) {throw new RuntimeException(lce);}
}
}).
addSynchronousTransition(LifecycleHandlerType.STOP, LifecycleHandlerType.POST_STOP,
new TransitionAction() {
@Override public void transit(Object[] params) {
PostStopHandler h = store.getHandler(LifecycleHandlerType.POST_STOP, PostStopHandler.class);
h.execute(ec);
try { h.execute(ec); } catch(LifecycleException lce) {throw new RuntimeException(lce);}
}
});
}
......
......@@ -65,16 +65,23 @@ final class StartDetectorHandler {
private DetectorState runStartDetectorLoop() {
boolean preprocessed = false;
try {
getLogger().info("running start detector");
getLogger().info("running start detector");
interceptor.preprocessDetector(DetectorType.START);
preprocessed = true;
return detector.execute(ec);
} catch (ContainerException ce) {
getLogger().warn("detection failed with exception", ce);
getLogger().warn("detection failed with exception", ce);
return DetectorState.DETECTION_FAILED;
} finally {
if(preprocessed) {
interceptor.postprocessDetector(DetectorType.START);
try {
interceptor.postprocessDetector(DetectorType.START);
} catch (ContainerException ce) {
// FIXME: what shall we do here? easiest is to disallow
// exceptions in postprocessing ...
getLogger().warn("error when postprocessing detection", ce);
throw new IllegalStateException("wrong state: should be in error state?", ce);
}
}
}
}
......
......@@ -7,6 +7,7 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import de.uniulm.omi.cloudiator.lance.lca.container.ComponentInstanceId;
import de.uniulm.omi.cloudiator.lance.lca.container.ContainerException;
......@@ -25,6 +26,8 @@ public class DummyInterceptor implements LifecycleActionInterceptor {
private volatile HandlerType ongoingPreparation = null;
private final static HandlerType portUpdateType = new HandlerType(){};
private final Map<HandlerType, List<Integer>> failureMap = new HashMap<>();
@Override
public void prepare(HandlerType type) throws ContainerException {
......@@ -38,10 +41,11 @@ public class DummyInterceptor implements LifecycleActionInterceptor {
countingHandlerCalls.put(type, 1);
invocations.add("prepare_"+type);
called.add(type);
checkForFailure(type);
}
@Override
public void postprocess(HandlerType type) {
public void postprocess(HandlerType type) throws ContainerException {
if(!countingHandlerCalls.containsKey(type)) {
throw new IllegalStateException("prepare handler not called: " + type);
}
......@@ -52,6 +56,7 @@ public class DummyInterceptor implements LifecycleActionInterceptor {
countingHandlerCalls.put(type, i+1);
ongoingPreparation = null;
invocations.add("postprocess_"+type);
checkForFailure(type);
}
@Override
......@@ -61,7 +66,7 @@ public class DummyInterceptor implements LifecycleActionInterceptor {
}
@Override
public void postprocessPortUpdate(PortDiff<DownstreamAddress> diff) {
public void postprocessPortUpdate(PortDiff<DownstreamAddress> diff) throws ContainerException {
if(!countingHandlerCalls.containsKey(portUpdateType)) {
throw new IllegalStateException("prepare port update handler not called");
}
......@@ -72,6 +77,7 @@ public class DummyInterceptor implements LifecycleActionInterceptor {
countingHandlerCalls.put(portUpdateType, i+1);
ongoingPreparation = null;
invocations.add("postprocessPortUpdate_"+diff);
checkForFailure(portUpdateType);
}
@Override
......@@ -86,11 +92,11 @@ public class DummyInterceptor implements LifecycleActionInterceptor {
countingHandlerCalls.put(portUpdateType, 1);
invocations.add("preprocessPortUpdate_"+diff);
called.add(portUpdateType);
throw new UnsupportedOperationException();
checkForFailure(portUpdateType);
}
@Override
public void postprocessDetector(DetectorType type) {
public void postprocessDetector(DetectorType type) throws ContainerException {
if(!countingHandlerCalls.containsKey(type)) {
throw new IllegalStateException("prepare detector handler not called: " + type + ": " +called);
}
......@@ -101,6 +107,7 @@ public class DummyInterceptor implements LifecycleActionInterceptor {
countingHandlerCalls.put(type, i+1);
ongoingPreparation = null;
invocations.add("postprocessDetector_"+type);
checkForFailure(type);
}
@Override
......@@ -108,13 +115,15 @@ public class DummyInterceptor implements LifecycleActionInterceptor {
if(ongoingPreparation != null) {
throw new IllegalStateException("preparation is ongoing: " + ongoingPreparation);
}
int number = 0;
if(countingHandlerCalls.containsKey(type)) {
throw new IllegalStateException("handler called twice: " + type);
countingHandlerCalls.get(type);
}
ongoingPreparation = type;
countingHandlerCalls.put(type, 1);
countingHandlerCalls.put(type, number + 1);
invocations.add("preprocessDetector_"+type);
called.add(type);
checkForFailure(type);
}
public int handlerCalls() {
......@@ -132,5 +141,34 @@ public class DummyInterceptor implements LifecycleActionInterceptor {
public List<HandlerType> invokedHandlers() {
return new ArrayList<>(called);
}
public DummyInterceptor failsAt(HandlerType t, boolean preprocess, int iteration) {
if(iteration < 0) throw new IllegalArgumentException();
int count = iteration * 2 + (preprocess ? 1 : 2);
addToFailure(t, count);
return this;
}
private void checkForFailure(HandlerType t) throws ContainerException {
Integer i = countingHandlerCalls.get(t);
if(i == null) {
throw new IllegalStateException();
}
List<Integer> j = failureMap.get(t);
if(j == null)
return;
if(j.contains(i)){
throw new ContainerException();
}
}
private void addToFailure(HandlerType t, int count) {
List<Integer> l = failureMap.get(t);
if(l == null) {
l = new ArrayList<>();
failureMap.put(t, l);
}
l.add(count);
}
}
......@@ -84,6 +84,38 @@ public class ComponentInstanceLifecycleTest {
checkBasicRegistryValue(1, LifecycleHandlerType.NEW);
}
@Test
public void failingInitWithMinimalStore() throws RegistrationException {
bootstrap(true);
creator.addEmptyStartHandler();
creator.addDefaultStartDetector();
createLifecycleController(true);
interceptor.failsAt(LifecycleHandlerType.NEW, true, 0);
lcc.blockingInit();
assertEquals(2, interceptor.handlerCalls());
assertEquals(Arrays.asList(new HandlerType[]{LifecycleHandlerType.NEW}),
interceptor.invokedHandlers());
checkBasicRegistryValue(1, LifecycleHandlerType.NEW);
}
@Test
public void failingInstallHandler() throws RegistrationException {
bootstrap(true);
creator.addEmptyStartHandler();
creator.addLifecycleHandler(LifecycleHandlerType.INIT, true);
creator.addDefaultStartDetector();
createLifecycleController(true);
lcc.blockingInit();
lcc.blockingInstall();
assertEquals(6, interceptor.handlerCalls());
assertEquals(Arrays.asList(new HandlerType[]{
LifecycleHandlerType.NEW, LifecycleHandlerType.INIT, LifecycleHandlerType.PRE_INSTALL, }),
interceptor.invokedHandlers());
checkBasicRegistryValue(1, LifecycleHandlerType.PRE_INSTALL);
}
@Test
public void installWithMinimalStore() throws RegistrationException {
bootstrap(true);
......@@ -129,16 +161,37 @@ public class ComponentInstanceLifecycleTest {
lcc.blockingStart();
assertEquals(16, interceptor.handlerCalls());
System.out.println(interceptor.invokedHandlers());
assertEquals(Arrays.asList(new HandlerType[]{
LifecycleHandlerType.NEW, LifecycleHandlerType.INIT, LifecycleHandlerType.PRE_INSTALL,
LifecycleHandlerType.INSTALL, LifecycleHandlerType.POST_INSTALL, LifecycleHandlerType.PRE_START,
DetectorType.START, LifecycleHandlerType.START}),
interceptor.invokedHandlers());
checkBasicRegistryValue(1, LifecycleHandlerType.START);
assertTrue("handler was not called", creator.checkHandlerHasBeenInvoked(LifecycleHandlerType.START, 1));
assertTrue("handler was not called", creator.checkHandlerHasBeenInvoked(DetectorType.START, 1));
}
@Test
public void longStartWithMinimalStore() throws RegistrationException, LifecycleException {
bootstrap(true);
creator.addEmptyStartHandler();
creator.addDefaultStartDetector(3);
createLifecycleController(true);
lcc.blockingInit();
lcc.blockingInstall();
lcc.blockingConfigure();
lcc.blockingStart();
assertEquals(16, interceptor.handlerCalls());
assertEquals(Arrays.asList(new HandlerType[]{
LifecycleHandlerType.NEW, LifecycleHandlerType.INIT, LifecycleHandlerType.PRE_INSTALL,
LifecycleHandlerType.INSTALL, LifecycleHandlerType.POST_INSTALL, LifecycleHandlerType.PRE_START,
DetectorType.START, DetectorType.START, DetectorType.START, LifecycleHandlerType.START}),
interceptor.invokedHandlers());
checkBasicRegistryValue(1, LifecycleHandlerType.START);
assertTrue("handler was not called", creator.checkHandlerHasBeenInvoked(LifecycleHandlerType.START));
assertTrue("handler was not called", creator.checkHandlerHasBeenInvoked(DetectorType.START));
assertTrue("handler was not called", creator.checkHandlerHasBeenInvoked(LifecycleHandlerType.START, 1));
assertTrue("handler was not called", creator.checkHandlerHasBeenInvoked(DetectorType.START, 3));
}
private void checkBasicRegistryValue(int compInstances, LifecycleHandlerType expectedType) throws RegistrationException {
......
......@@ -33,7 +33,11 @@ public class LifecycleStoreCreator {
}
public LifecycleStoreCreator addDefaultStartDetector() {
TestLifecycleHandler h = new TestLifecycleHandler(DetectorType.START);
return addDefaultStartDetector(1);
}
public LifecycleStoreCreator addDefaultStartDetector(int i) {
TestLifecycleHandler h = new TestLifecycleHandler(DetectorType.START, i, false);
StartDetector hh = createProxy(h, StartDetector.class);
builder.setStartDetector(hh);
addToMapping(DetectorType.START, h);
......@@ -51,10 +55,18 @@ public class LifecycleStoreCreator {
addToMapping(LifecycleHandlerType.START, h);
return this;
}
public LifecycleStoreCreator addLifecycleHandler(LifecycleHandlerType type, boolean throwsException) {
TestLifecycleHandler h = new TestLifecycleHandler(type, throwsException);
LifecycleHandler hh = createProxy(h, type.getTypeClass());
builder.setHandler(hh, type);
addToMapping(type, h);
return this;
}
public boolean checkHandlerHasBeenInvoked(HandlerType type) {
public boolean checkHandlerHasBeenInvoked(HandlerType type, int i) {
TestLifecycleHandler h = mapping.get(type);
return h.wasCalled();
return h.wasCalled(i);
}
}
......@@ -2,39 +2,51 @@ package de.uniulm.omi.cloudiator.lance.lifecycles;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Stack;
import de.uniulm.omi.cloudiator.lance.lifecycle.ExecutionContext;
import de.uniulm.omi.cloudiator.lance.lifecycle.HandlerType;
import de.uniulm.omi.cloudiator.lance.lifecycle.LifecycleHandler;
import de.uniulm.omi.cloudiator.lance.lifecycle.detector.Detector;
import de.uniulm.omi.cloudiator.lance.lifecycle.LifecycleException;
import de.uniulm.omi.cloudiator.lance.lifecycle.LifecycleHandlerType;
import de.uniulm.omi.cloudiator.lance.lifecycle.detector.DetectorState;
import de.uniulm.omi.cloudiator.lance.lifecycle.detector.DetectorType;
import de.uniulm.omi.cloudiator.lance.lifecycle.detector.StartDetector;
public class TestLifecycleHandler implements InvocationHandler {
public final HandlerType type;
public volatile ExecutionContext ec = null;
public volatile Stack<ExecutionContext> ec = new Stack<>();
public final boolean throwsException;
public final int count;
public TestLifecycleHandler(HandlerType myType, boolean throwException) {
type = myType;
throwsException = throwException;
count = 0;
}
public TestLifecycleHandler(HandlerType myType) {
public TestLifecycleHandler(LifecycleHandlerType myType) {
this(myType, false);
}
public Object execute(ExecutionContext ec) {
public TestLifecycleHandler(DetectorType start, int i, boolean throwException) {
type = start;
throwsException = throwException;
count = i;
}
public Object execute(ExecutionContext ec) throws LifecycleException {
if(ec == null)
throw new NullPointerException();
this.ec = ec;
this.ec.push(ec);
if(throwsException){
throw new RuntimeException();
throw new LifecycleException("cold not execute command 'ls' in " + type + " handler.");
}
if(type == DetectorType.START) {
return DetectorState.DETECTED;
if(this.ec.size() == count)
return DetectorState.DETECTED;
if(this.ec.size() < count)
return DetectorState.NOT_DETECTED;
throw new IllegalStateException();
}
return null;
}
......@@ -47,7 +59,7 @@ public class TestLifecycleHandler implements InvocationHandler {
throw new IllegalArgumentException(method.toString());
}
public boolean wasCalled() {
return ec != null;
public boolean wasCalled(int i) {
return ec.size() == i;
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment