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