package jetbrains.mps.baseLanguage.unitTest.execution.server;
/*Generated by MPS */
import org.apache.log4j.Logger;
import org.apache.log4j.LogManager;
import jetbrains.mps.baseLanguage.unitTest.execution.client.TestEventsDispatcher;
import jetbrains.mps.baseLanguage.unitTest.execution.client.ITestNodeWrapper;
import jetbrains.mps.lang.test.util.TestInProcessRunState;
import jetbrains.mps.execution.configurations.implementation.plugin.plugin.FakeProcess;
import com.intellij.util.WaitFor;
import jetbrains.mps.lang.test.util.RunStateEnum;
import org.junit.runner.JUnitCore;
import org.junit.runner.Request;
import org.apache.log4j.Level;
import jetbrains.mps.TestMode;
import jetbrains.mps.RuntimeFlags;
import org.junit.runner.notification.StoppedByUserException;
import org.jetbrains.annotations.NotNull;
import org.junit.runner.notification.RunListener;
public class TestInProcessExecutor extends AbstractTestExecutor {
private static final Logger LOG = LogManager.getLogger(TestInProcessExecutor.class);
private static final int MSECS_TO_WAIT_FOR_START = 50 * 1000;
private final TestEventsDispatcher myDispatcher;
private final Iterable<? extends ITestNodeWrapper> myNodes;
private final TestInProcessRunState myTestRunState;
private final FakeProcess myFakeProcess = new FakeProcess();
private volatile DefaultRunListener myTestRunListener = null;
public TestInProcessExecutor(TestEventsDispatcher dispatcher, Iterable<? extends ITestNodeWrapper> nodes, TestInProcessRunState testRunState) {
myDispatcher = dispatcher;
myNodes = nodes;
myTestRunState = testRunState;
myFilter = new InProcessExecutionFilter();
}
private void waitWhileNotReady() {
new WaitFor(MSECS_TO_WAIT_FOR_START) {
@Override
protected boolean condition() {
return myTestRunState.isReady();
}
};
if (!(myTestRunState.isReady())) {
throw new TestInProcessExecutor.IllegalProcessStateError("Process is not ready");
}
}
@Override
public void init() {
if (LOG.isDebugEnabled()) {
LOG.debug("Initializing TestInProcessExecutor");
}
waitWhileNotReady();
}
@Override
public void dispose() {
if (LOG.isDebugEnabled()) {
LOG.debug("Disposing TestLightExecutor");
}
myTestRunState.set(RunStateEnum.TERMINATED);
myFakeProcess.destroy();
}
public FakeProcess getProcess() {
return myFakeProcess;
}
public void setReady() {
myTestRunState.advance(RunStateEnum.INITIALIZED, RunStateEnum.READYTOEXECUTE);
}
@Override
protected void doExecute(JUnitCore core, Iterable<Request> requests) throws Throwable {
assert myTestRunState.isReady();
if (LOG.isEnabledFor(Level.WARN)) {
LOG.warn("Be aware of the execution of your own test code and its consequences when running tests in-process. " + "The code is being executed within the current MPS environment and might do a lot of damage if written without caution.");
}
if (LOG.isInfoEnabled()) {
LOG.info("Executing tests in-process");
}
myTestRunState.advance(RunStateEnum.READYTOEXECUTE, RunStateEnum.RUNNING);
TestMode oldTestMode = RuntimeFlags.getTestMode();
try {
RuntimeFlags.setTestMode(TestMode.IN_PROCESS);
super.doExecute(core, requests);
myFakeProcess.setExitCode(myTestRunListener.getFailureCount());
} catch (StoppedByUserException exception) {
// will be thrown eventually when #terminateRun is called
terminateProcess(FakeProcess.TERMINATION_CODE);
} finally {
RuntimeFlags.setTestMode(oldTestMode);
}
}
public void terminateRun() {
if (!(myTestRunState.isTerminated())) {
stopRun();
}
}
/*package*/ void terminateProcess(int code) {
myTestRunState.advance(RunStateEnum.RUNNING, RunStateEnum.TERMINATING);
myFakeProcess.setExitCode(code);
String terminateMessage = "Process finished with exit code " + code;
if (LOG.isInfoEnabled()) {
LOG.info(terminateMessage);
}
myDispatcher.onProcessTerminated(terminateMessage);
}
@NotNull
@Override
protected TestsContributor createTestsContributor() {
return new NodeWrappersTestsContributor(myNodes);
}
@NotNull
@Override
protected RunListener createListener(Iterable<Request> requests) {
myTestRunListener = new DefaultRunListener(new CommandOutputStream(System.out));
return myTestRunListener;
}
private static class IllegalProcessStateError extends Error {
public IllegalProcessStateError(String msg) {
super(msg);
}
}
}