package jetbrains.mps.execution.configurations.implementation.plugin.plugin;
/*Generated by MPS */
import jetbrains.mps.baseLanguage.unitTest.execution.client.ITestNodeWrapper;
import jetbrains.mps.baseLanguage.unitTest.execution.client.TestEventsDispatcher;
import jetbrains.mps.baseLanguage.unitTest.execution.server.TestInProcessExecutor;
import jetbrains.mps.lang.test.util.TestInProcessRunState;
import jetbrains.mps.lang.test.util.RunStateEnum;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.ExecutionException;
import jetbrains.mps.internal.collections.runtime.Sequence;
import java.util.concurrent.Future;
import jetbrains.mps.baseLanguage.unitTest.execution.server.TestExecutor;
import com.intellij.openapi.application.ApplicationManager;
import org.jetbrains.annotations.Nullable;
import java.io.OutputStream;
import com.intellij.execution.process.ProcessOutputTypes;
public class JUnitInProcessExecutor implements Executor {
private final Iterable<ITestNodeWrapper> myNodes;
private final TestEventsDispatcher myDispatcher;
private TestInProcessExecutor myExecutor;
private static volatile TestInProcessRunState ourTestRunState = new TestInProcessRunState();
public JUnitInProcessExecutor(Iterable<ITestNodeWrapper> testNodeWrappers, TestEventsDispatcher dispatcher) {
myNodes = testNodeWrappers;
myDispatcher = dispatcher;
}
private synchronized boolean checkExecutionIsPossible() {
boolean isPossible = ourTestRunState.advance(RunStateEnum.IDLE, RunStateEnum.INITIALIZED);
return isPossible;
}
@Override
public ProcessHandler execute() throws ExecutionException {
if (myNodes == null || Sequence.fromIterable(myNodes).isEmpty()) {
throw new ExecutionException("Could not find tests to run");
}
if (!(checkExecutionIsPossible())) {
return new JUnitInProcessExecutor.EmptyProcessHandler();
}
myExecutor = new TestInProcessExecutor(myDispatcher, myNodes, ourTestRunState);
final Future<?> future = doExecute(myExecutor);
final FakeProcessHandler process = new FakeProcessHandler(myExecutor.getProcess(), future, myExecutor);
return process;
}
private Future<?> doExecute(final TestExecutor executor) {
return ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
@Override
public void run() {
try {
executor.init();
executor.execute();
} finally {
executor.dispose();
JUnitInProcessExecutor.this.dispose();
}
}
});
}
/**
* FOR TEST USE ONLY
*/
public static TestInProcessRunState getRunState() {
return ourTestRunState;
}
private void dispose() {
ourTestRunState.reset();
}
private class EmptyProcessHandler extends ProcessHandler {
protected void destroyProcessImpl() {
myExecutor.terminateRun();
}
protected void detachProcessImpl() {
myExecutor.terminateRun();
}
public boolean detachIsDefault() {
return false;
}
@Nullable
public OutputStream getProcessInput() {
return null;
}
@Override
public boolean isProcessTerminated() {
return true;
}
@Override
public void startNotify() {
super.startNotify();
String terminateMessage = "Only one test instance is allowed to run in process.\n" + "To run in the outer process change the corresponding property in the junit run configuration.\n" + "Process finished with exit code " + -1 + ".\n";
myDispatcher.onSimpleTextAvailable(terminateMessage, ProcessOutputTypes.STDERR);
myDispatcher.onProcessTerminated(terminateMessage);
this.notifyProcessTerminated(-1);
}
}
}