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); } } }