mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Memory leak in AbstractRerunFailedTestsAction
This commit is contained in:
+14
-9
@@ -30,14 +30,13 @@ import com.intellij.execution.runners.ExecutionEnvironment;
|
||||
import com.intellij.execution.runners.ProgramRunner;
|
||||
import com.intellij.execution.testframework.*;
|
||||
import com.intellij.idea.ActionsBundle;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.options.SettingsEditor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Getter;
|
||||
import com.intellij.openapi.util.InvalidDataException;
|
||||
import com.intellij.openapi.util.JDOMExternalizable;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.openapi.ui.ComponentContainer;
|
||||
import com.intellij.openapi.util.*;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -48,9 +47,10 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
public class AbstractRerunFailedTestsAction extends AnAction implements AnAction.TransparentUpdate {
|
||||
private static List<AbstractRerunFailedTestsAction> registry = new ArrayList<AbstractRerunFailedTestsAction>();
|
||||
public class AbstractRerunFailedTestsAction extends AnAction implements AnAction.TransparentUpdate, Disposable {
|
||||
private static List<AbstractRerunFailedTestsAction> registry = new CopyOnWriteArrayList<AbstractRerunFailedTestsAction>();
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.execution.junit2.ui.actions.RerunFailedTestsAction");
|
||||
private TestFrameworkRunningModel myModel;
|
||||
private Getter<TestFrameworkRunningModel> myModelProvider;
|
||||
@@ -64,11 +64,16 @@ public class AbstractRerunFailedTestsAction extends AnAction implements AnAction
|
||||
myParent = null;
|
||||
}
|
||||
|
||||
protected AbstractRerunFailedTestsAction(JComponent parent) {
|
||||
myParent = parent;
|
||||
protected AbstractRerunFailedTestsAction(@NotNull ComponentContainer componentContainer) {
|
||||
myParent = componentContainer.getComponent();
|
||||
registry.add(this);
|
||||
Disposer.register(componentContainer, this);
|
||||
copyFrom(ActionManager.getInstance().getAction("RerunFailedTests"));
|
||||
registerCustomShortcutSet(getShortcutSet(), parent);
|
||||
registerCustomShortcutSet(getShortcutSet(), myParent);
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
registry.remove(this);
|
||||
}
|
||||
|
||||
public void init(final TestConsoleProperties consoleProperties,
|
||||
|
||||
@@ -1,445 +1,445 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.intellij.execution.junit;
|
||||
|
||||
import com.intellij.ExtensionPoints;
|
||||
import com.intellij.execution.*;
|
||||
import com.intellij.execution.configurations.*;
|
||||
import com.intellij.execution.junit2.TestProxy;
|
||||
import com.intellij.execution.junit2.segments.DeferredActionsQueue;
|
||||
import com.intellij.execution.junit2.segments.DeferredActionsQueueImpl;
|
||||
import com.intellij.execution.junit2.segments.DispatchListener;
|
||||
import com.intellij.execution.junit2.segments.Extractor;
|
||||
import com.intellij.execution.junit2.ui.JUnitTreeConsoleView;
|
||||
import com.intellij.execution.junit2.ui.TestsPacketsReceiver;
|
||||
import com.intellij.execution.junit2.ui.actions.RerunFailedTestsAction;
|
||||
import com.intellij.execution.junit2.ui.model.JUnitRunningModel;
|
||||
import com.intellij.execution.junit2.ui.model.RootTestInfo;
|
||||
import com.intellij.execution.junit2.ui.properties.JUnitConsoleProperties;
|
||||
import com.intellij.execution.process.ProcessAdapter;
|
||||
import com.intellij.execution.process.ProcessEvent;
|
||||
import com.intellij.execution.runners.ExecutionEnvironment;
|
||||
import com.intellij.execution.runners.ProgramRunner;
|
||||
import com.intellij.execution.testframework.*;
|
||||
import com.intellij.execution.ui.ConsoleViewContentType;
|
||||
import com.intellij.execution.util.JavaParametersUtil;
|
||||
import com.intellij.execution.util.ProgramParametersUtil;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkType;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.ex.JavaSdkUtil;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Getter;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiPackage;
|
||||
import com.intellij.refactoring.listeners.RefactoringElementListener;
|
||||
import com.intellij.rt.execution.junit.IDEAJUnitListener;
|
||||
import com.intellij.rt.execution.junit.JUnitStarter;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.IJSwingUtilities;
|
||||
import com.intellij.util.PathUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class TestObject implements JavaCommandLine {
|
||||
protected static final Logger LOG = Logger.getInstance("#com.intellij.execution.junit.TestObject");
|
||||
|
||||
private static final String MESSAGE = ExecutionBundle.message("configuration.not.speficied.message");
|
||||
|
||||
protected JavaParameters myJavaParameters;
|
||||
private final Project myProject;
|
||||
protected final JUnitConfiguration myConfiguration;
|
||||
private final ExecutionEnvironment myEnvironment;
|
||||
protected File myTempFile = null;
|
||||
public File myListenersFile;
|
||||
|
||||
public static TestObject fromString(final String id,
|
||||
final Project project,
|
||||
final JUnitConfiguration configuration,
|
||||
ExecutionEnvironment environment) {
|
||||
if (JUnitConfiguration.TEST_METHOD.equals(id))
|
||||
return new TestMethod(project, configuration, environment);
|
||||
if (JUnitConfiguration.TEST_CLASS.equals(id))
|
||||
return new TestClass(project, configuration, environment);
|
||||
if (JUnitConfiguration.TEST_PACKAGE.equals(id))
|
||||
return new TestPackage(project, configuration, environment);
|
||||
else if (JUnitConfiguration.TEST_DIRECTORY.equals(id)) {
|
||||
return new TestDirectory(project, configuration, environment);
|
||||
}
|
||||
if (JUnitConfiguration.TEST_PATTERN.equals(id)) {
|
||||
return new TestsPattern(project, configuration, environment);
|
||||
}
|
||||
return NOT_CONFIGURED;
|
||||
}
|
||||
|
||||
public Module[] getModulesToCompile() {
|
||||
final SourceScope sourceScope = getSourceScope();
|
||||
return sourceScope != null ? sourceScope.getModulesToCompile() : Module.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
protected TestObject(final Project project,
|
||||
final JUnitConfiguration configuration,
|
||||
ExecutionEnvironment environment) {
|
||||
myProject = project;
|
||||
myConfiguration = configuration;
|
||||
myEnvironment = environment;
|
||||
}
|
||||
|
||||
public abstract String suggestActionName();
|
||||
|
||||
@Override
|
||||
public RunnerSettings getRunnerSettings() {
|
||||
return myEnvironment.getRunnerSettings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurationPerRunnerSettings getConfigurationSettings() {
|
||||
return myEnvironment.getConfigurationSettings();
|
||||
}
|
||||
|
||||
public abstract RefactoringElementListener getListener(PsiElement element, JUnitConfiguration configuration);
|
||||
|
||||
public abstract boolean isConfiguredByElement(JUnitConfiguration configuration,
|
||||
PsiClass testClass,
|
||||
PsiMethod testMethod,
|
||||
PsiPackage testPackage);
|
||||
|
||||
protected void configureModule(final JavaParameters parameters, final RunConfigurationModule configurationModule, final String mainClassName)
|
||||
throws CantRunException {
|
||||
int classPathType = JavaParametersUtil.getClasspathType(configurationModule, mainClassName, true);
|
||||
JavaParametersUtil.configureModule(configurationModule, parameters, classPathType,
|
||||
myConfiguration.isAlternativeJrePathEnabled() ? myConfiguration.getAlternativeJrePath() : null);
|
||||
}
|
||||
|
||||
private static final TestObject NOT_CONFIGURED = new TestObject(null, null, null) {
|
||||
@Override
|
||||
public RefactoringElementListener getListener(final PsiElement element, final JUnitConfiguration configuration) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String suggestActionName() {
|
||||
throw new RuntimeException(String.valueOf(myConfiguration));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConfiguredByElement(final JUnitConfiguration configuration,
|
||||
PsiClass testClass,
|
||||
PsiMethod testMethod,
|
||||
PsiPackage testPackage) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkConfiguration() throws RuntimeConfigurationException {
|
||||
throw new RuntimeConfigurationError(MESSAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaParameters getJavaParameters() throws ExecutionException {
|
||||
throw new ExecutionException(MESSAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialize() throws ExecutionException {
|
||||
throw new ExecutionException(MESSAGE);
|
||||
}
|
||||
};
|
||||
|
||||
public void checkConfiguration() throws RuntimeConfigurationException{
|
||||
JavaParametersUtil.checkAlternativeJRE(myConfiguration);
|
||||
ProgramParametersUtil.checkWorkingDirectoryExist(myConfiguration, myConfiguration.getProject(), myConfiguration.getConfigurationModule().getModule());
|
||||
}
|
||||
|
||||
public SourceScope getSourceScope() {
|
||||
return SourceScope.modulesWithDependencies(myConfiguration.getModules());
|
||||
}
|
||||
|
||||
protected void initialize() throws ExecutionException {
|
||||
JavaParametersUtil.configureConfiguration(myJavaParameters, myConfiguration);
|
||||
myJavaParameters.setMainClass(JUnitConfiguration.JUNIT_START_CLASS);
|
||||
final Module module = myConfiguration.getConfigurationModule().getModule();
|
||||
if (myJavaParameters.getJdk() == null){
|
||||
myJavaParameters.setJdk(module != null
|
||||
? ModuleRootManager.getInstance(module).getSdk()
|
||||
: ProjectRootManager.getInstance(myProject).getProjectSdk());
|
||||
}
|
||||
|
||||
myJavaParameters.getClassPath().add(JavaSdkUtil.getIdeaRtJarPath());
|
||||
myJavaParameters.getClassPath().add(PathUtil.getJarPathForClass(JUnitStarter.class));
|
||||
myJavaParameters.getProgramParametersList().add(JUnitStarter.IDE_VERSION + JUnitStarter.VERSION);
|
||||
for (RunConfigurationExtension ext : Extensions.getExtensions(RunConfigurationExtension.EP_NAME)) {
|
||||
ext.updateJavaParameters(myConfiguration, myJavaParameters, getRunnerSettings());
|
||||
}
|
||||
|
||||
final Object[] listeners = Extensions.getExtensions(IDEAJUnitListener.EP_NAME);
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
for (final Object listener : listeners) {
|
||||
boolean enabled = true;
|
||||
for (RunConfigurationExtension ext : Extensions.getExtensions(RunConfigurationExtension.EP_NAME)) {
|
||||
if (ext.isListenerDisabled(myConfiguration, listener, getRunnerSettings())) {
|
||||
enabled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (enabled) {
|
||||
final Class classListener = listener.getClass();
|
||||
buf.append(classListener.getName()).append("\n");
|
||||
myJavaParameters.getClassPath().add(PathUtil.getJarPathForClass(classListener));
|
||||
}
|
||||
}
|
||||
if (buf.length() > 0) {
|
||||
try {
|
||||
myListenersFile = FileUtil.createTempFile("junit_listeners_", "");
|
||||
myListenersFile.deleteOnExit();
|
||||
myJavaParameters.getProgramParametersList().add("@@" + myListenersFile.getPath());
|
||||
FileUtil.writeToFile(myListenersFile, buf.toString().getBytes());
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaParameters getJavaParameters() throws ExecutionException {
|
||||
if (myJavaParameters == null) {
|
||||
myJavaParameters = new JavaParameters();
|
||||
initialize();
|
||||
final Module module = myConfiguration.getConfigurationModule().getModule();
|
||||
final Object[] patchers = Extensions.getExtensions(ExtensionPoints.JUNIT_PATCHER);
|
||||
for (Object patcher : patchers) {
|
||||
((JUnitPatcher)patcher).patchJavaParameters(module, myJavaParameters);
|
||||
}
|
||||
}
|
||||
return myJavaParameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecutionResult execute(final Executor executor, @NotNull final ProgramRunner runner) throws ExecutionException {
|
||||
final JUnitProcessHandler handler = createHandler(executor);
|
||||
final RunnerSettings runnerSettings = getRunnerSettings();
|
||||
JavaRunConfigurationExtensionManager.getInstance().attachExtensionsToProcess(myConfiguration, handler, runnerSettings);
|
||||
final TestProxy unboundOutputRoot = new TestProxy(new RootTestInfo());
|
||||
final JUnitConsoleProperties consoleProperties = new JUnitConsoleProperties(myConfiguration, executor);
|
||||
final JUnitTreeConsoleView consoleView = new JUnitTreeConsoleView(consoleProperties, runnerSettings, getConfigurationSettings(), unboundOutputRoot);
|
||||
consoleView.initUI();
|
||||
consoleView.attachToProcess(handler);
|
||||
unboundOutputRoot.setPrinter(consoleView.getPrinter());
|
||||
Disposer.register(consoleView, unboundOutputRoot);
|
||||
final TestsPacketsReceiver packetsReceiver = new TestsPacketsReceiver(consoleView, unboundOutputRoot) {
|
||||
@Override
|
||||
public void notifyStart(TestProxy root) {
|
||||
if (!isRunning()) return;
|
||||
super.notifyStart(root);
|
||||
unboundOutputRoot.addChild(root);
|
||||
if (myConfiguration.isSaveOutputToFile()) {
|
||||
unboundOutputRoot.setOutputFilePath(myConfiguration.getOutputFilePath());
|
||||
}
|
||||
final JUnitRunningModel model = getModel();
|
||||
if (model != null) {
|
||||
handler.getOut().setDispatchListener(model.getNotifier());
|
||||
Disposer.register(model, new Disposable() {
|
||||
@Override
|
||||
public void dispose() {
|
||||
handler.getOut().setDispatchListener(DispatchListener.DEAF);
|
||||
}
|
||||
});
|
||||
consoleView.attachToModel(model);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
final DeferredActionsQueue queue = new DeferredActionsQueueImpl();
|
||||
handler.getOut().setPacketDispatcher(packetsReceiver, queue);
|
||||
handler.getErr().setPacketDispatcher(packetsReceiver, queue);
|
||||
|
||||
handler.addProcessListener(new ProcessAdapter() {
|
||||
@Override
|
||||
public void processTerminated(ProcessEvent event) {
|
||||
handler.removeProcessListener(this);
|
||||
if (myTempFile != null) {
|
||||
FileUtil.delete(myTempFile);
|
||||
}
|
||||
if (myListenersFile != null) {
|
||||
FileUtil.delete(myListenersFile);
|
||||
}
|
||||
IJSwingUtilities.invoke(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
unboundOutputRoot.flush();
|
||||
packetsReceiver.checkTerminated();
|
||||
final JUnitRunningModel model = packetsReceiver.getModel();
|
||||
notifyByBalloon(model, consoleProperties);
|
||||
}
|
||||
finally {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
Disposer.dispose(consoleView);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextAvailable(final ProcessEvent event, final Key outputType) {
|
||||
final String text = event.getText();
|
||||
final ConsoleViewContentType consoleViewType = ConsoleViewContentType.getConsoleViewType(outputType);
|
||||
final Printable printable = new Printable() {
|
||||
@Override
|
||||
public void printOn(final Printer printer) {
|
||||
printer.print(text, consoleViewType);
|
||||
}
|
||||
};
|
||||
final Extractor extractor;
|
||||
if (consoleViewType == ConsoleViewContentType.ERROR_OUTPUT ||
|
||||
consoleViewType == ConsoleViewContentType.SYSTEM_OUTPUT) {
|
||||
extractor = handler.getErr();
|
||||
}
|
||||
else {
|
||||
extractor = handler.getOut();
|
||||
}
|
||||
extractor.getEventsDispatcher().processOutput(printable);
|
||||
}
|
||||
});
|
||||
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
return new DefaultExecutionResult(null, handler);
|
||||
}
|
||||
|
||||
final RerunFailedTestsAction rerunFailedTestsAction = new RerunFailedTestsAction(consoleView.getComponent());
|
||||
rerunFailedTestsAction.init(consoleProperties, myEnvironment);
|
||||
rerunFailedTestsAction.setModelProvider(new Getter<TestFrameworkRunningModel>() {
|
||||
@Override
|
||||
public TestFrameworkRunningModel get() {
|
||||
return packetsReceiver.getModel();
|
||||
}
|
||||
});
|
||||
|
||||
final DefaultExecutionResult result = new DefaultExecutionResult(consoleView, handler);
|
||||
result.setRestartActions(rerunFailedTestsAction);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void notifyByBalloon(JUnitRunningModel model, JUnitConsoleProperties consoleProperties) {
|
||||
TestsUIUtil.notifyByBalloon(myProject, model != null ? model.getRoot() : null, consoleProperties);
|
||||
}
|
||||
|
||||
protected JUnitProcessHandler createHandler(Executor executor) throws ExecutionException {
|
||||
appendForkInfo(executor);
|
||||
return JUnitProcessHandler.runCommandLine(CommandLineBuilder.createFromJavaParameters(myJavaParameters, myProject, true));
|
||||
}
|
||||
|
||||
private void appendForkInfo(Executor executor) throws ExecutionException {
|
||||
final String forkMode = myConfiguration.getForkMode();
|
||||
if (Comparing.strEqual(forkMode, "none")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (getRunnerSettings().getData() != null) {
|
||||
final String actionName = executor.getActionName();
|
||||
throw new CantRunException(actionName + " is disabled in fork mode.<br/>Please change fork mode to <none> to " + actionName.toLowerCase() + ".");
|
||||
}
|
||||
|
||||
final JavaParameters javaParameters = getJavaParameters();
|
||||
final Sdk jdk = javaParameters.getJdk();
|
||||
if (jdk == null) {
|
||||
throw new ExecutionException(ExecutionBundle.message("run.configuration.error.no.jdk.specified"));
|
||||
}
|
||||
|
||||
try {
|
||||
final File tempFile = FileUtil.createTempFile("command.line", "", true);
|
||||
final PrintWriter writer = new PrintWriter(tempFile, "UTF-8");
|
||||
try {
|
||||
writer.println(((JavaSdkType)jdk.getSdkType()).getVMExecutablePath(jdk));
|
||||
for (String vmParameter : javaParameters.getVMParametersList().getList()) {
|
||||
writer.println(vmParameter);
|
||||
}
|
||||
writer.println("-classpath");
|
||||
writer.println(javaParameters.getClassPath().getPathsString());
|
||||
}
|
||||
finally {
|
||||
writer.close();
|
||||
}
|
||||
|
||||
myJavaParameters.getProgramParametersList().add("@@@" + forkMode + ',' + tempFile.getAbsolutePath());
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected <T> void addClassesListToJavaParameters(Collection<? extends T> elements, Function<T, String> nameFunction, String packageName,
|
||||
boolean createTempFile,
|
||||
boolean junit4) {
|
||||
try {
|
||||
if (createTempFile) {
|
||||
myTempFile = FileUtil.createTempFile("idea_junit", ".tmp");
|
||||
myTempFile.deleteOnExit();
|
||||
myJavaParameters.getProgramParametersList().add("@" + myTempFile.getAbsolutePath());
|
||||
}
|
||||
|
||||
final PrintWriter writer = new PrintWriter(myTempFile, "UTF-8");
|
||||
try {
|
||||
writer.println(packageName);
|
||||
final List<String> testNames = new ArrayList<String>();
|
||||
for (final T element : elements) {
|
||||
final String name = nameFunction.fun(element);
|
||||
if (name == null) {
|
||||
LOG.error("invalid element " + element);
|
||||
return;
|
||||
}
|
||||
testNames.add(name);
|
||||
}
|
||||
Collections.sort(testNames); //sort tests in FQN order
|
||||
for (String testName : testNames) {
|
||||
writer.println(testName);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
myJavaParameters = null;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.intellij.execution.junit;
|
||||
|
||||
import com.intellij.ExtensionPoints;
|
||||
import com.intellij.execution.*;
|
||||
import com.intellij.execution.configurations.*;
|
||||
import com.intellij.execution.junit2.TestProxy;
|
||||
import com.intellij.execution.junit2.segments.DeferredActionsQueue;
|
||||
import com.intellij.execution.junit2.segments.DeferredActionsQueueImpl;
|
||||
import com.intellij.execution.junit2.segments.DispatchListener;
|
||||
import com.intellij.execution.junit2.segments.Extractor;
|
||||
import com.intellij.execution.junit2.ui.JUnitTreeConsoleView;
|
||||
import com.intellij.execution.junit2.ui.TestsPacketsReceiver;
|
||||
import com.intellij.execution.junit2.ui.actions.RerunFailedTestsAction;
|
||||
import com.intellij.execution.junit2.ui.model.JUnitRunningModel;
|
||||
import com.intellij.execution.junit2.ui.model.RootTestInfo;
|
||||
import com.intellij.execution.junit2.ui.properties.JUnitConsoleProperties;
|
||||
import com.intellij.execution.process.ProcessAdapter;
|
||||
import com.intellij.execution.process.ProcessEvent;
|
||||
import com.intellij.execution.runners.ExecutionEnvironment;
|
||||
import com.intellij.execution.runners.ProgramRunner;
|
||||
import com.intellij.execution.testframework.*;
|
||||
import com.intellij.execution.ui.ConsoleViewContentType;
|
||||
import com.intellij.execution.util.JavaParametersUtil;
|
||||
import com.intellij.execution.util.ProgramParametersUtil;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkType;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.ex.JavaSdkUtil;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Getter;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiPackage;
|
||||
import com.intellij.refactoring.listeners.RefactoringElementListener;
|
||||
import com.intellij.rt.execution.junit.IDEAJUnitListener;
|
||||
import com.intellij.rt.execution.junit.JUnitStarter;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.IJSwingUtilities;
|
||||
import com.intellij.util.PathUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class TestObject implements JavaCommandLine {
|
||||
protected static final Logger LOG = Logger.getInstance("#com.intellij.execution.junit.TestObject");
|
||||
|
||||
private static final String MESSAGE = ExecutionBundle.message("configuration.not.speficied.message");
|
||||
|
||||
protected JavaParameters myJavaParameters;
|
||||
private final Project myProject;
|
||||
protected final JUnitConfiguration myConfiguration;
|
||||
private final ExecutionEnvironment myEnvironment;
|
||||
protected File myTempFile = null;
|
||||
public File myListenersFile;
|
||||
|
||||
public static TestObject fromString(final String id,
|
||||
final Project project,
|
||||
final JUnitConfiguration configuration,
|
||||
ExecutionEnvironment environment) {
|
||||
if (JUnitConfiguration.TEST_METHOD.equals(id))
|
||||
return new TestMethod(project, configuration, environment);
|
||||
if (JUnitConfiguration.TEST_CLASS.equals(id))
|
||||
return new TestClass(project, configuration, environment);
|
||||
if (JUnitConfiguration.TEST_PACKAGE.equals(id))
|
||||
return new TestPackage(project, configuration, environment);
|
||||
else if (JUnitConfiguration.TEST_DIRECTORY.equals(id)) {
|
||||
return new TestDirectory(project, configuration, environment);
|
||||
}
|
||||
if (JUnitConfiguration.TEST_PATTERN.equals(id)) {
|
||||
return new TestsPattern(project, configuration, environment);
|
||||
}
|
||||
return NOT_CONFIGURED;
|
||||
}
|
||||
|
||||
public Module[] getModulesToCompile() {
|
||||
final SourceScope sourceScope = getSourceScope();
|
||||
return sourceScope != null ? sourceScope.getModulesToCompile() : Module.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
protected TestObject(final Project project,
|
||||
final JUnitConfiguration configuration,
|
||||
ExecutionEnvironment environment) {
|
||||
myProject = project;
|
||||
myConfiguration = configuration;
|
||||
myEnvironment = environment;
|
||||
}
|
||||
|
||||
public abstract String suggestActionName();
|
||||
|
||||
@Override
|
||||
public RunnerSettings getRunnerSettings() {
|
||||
return myEnvironment.getRunnerSettings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurationPerRunnerSettings getConfigurationSettings() {
|
||||
return myEnvironment.getConfigurationSettings();
|
||||
}
|
||||
|
||||
public abstract RefactoringElementListener getListener(PsiElement element, JUnitConfiguration configuration);
|
||||
|
||||
public abstract boolean isConfiguredByElement(JUnitConfiguration configuration,
|
||||
PsiClass testClass,
|
||||
PsiMethod testMethod,
|
||||
PsiPackage testPackage);
|
||||
|
||||
protected void configureModule(final JavaParameters parameters, final RunConfigurationModule configurationModule, final String mainClassName)
|
||||
throws CantRunException {
|
||||
int classPathType = JavaParametersUtil.getClasspathType(configurationModule, mainClassName, true);
|
||||
JavaParametersUtil.configureModule(configurationModule, parameters, classPathType,
|
||||
myConfiguration.isAlternativeJrePathEnabled() ? myConfiguration.getAlternativeJrePath() : null);
|
||||
}
|
||||
|
||||
private static final TestObject NOT_CONFIGURED = new TestObject(null, null, null) {
|
||||
@Override
|
||||
public RefactoringElementListener getListener(final PsiElement element, final JUnitConfiguration configuration) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String suggestActionName() {
|
||||
throw new RuntimeException(String.valueOf(myConfiguration));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConfiguredByElement(final JUnitConfiguration configuration,
|
||||
PsiClass testClass,
|
||||
PsiMethod testMethod,
|
||||
PsiPackage testPackage) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkConfiguration() throws RuntimeConfigurationException {
|
||||
throw new RuntimeConfigurationError(MESSAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaParameters getJavaParameters() throws ExecutionException {
|
||||
throw new ExecutionException(MESSAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialize() throws ExecutionException {
|
||||
throw new ExecutionException(MESSAGE);
|
||||
}
|
||||
};
|
||||
|
||||
public void checkConfiguration() throws RuntimeConfigurationException{
|
||||
JavaParametersUtil.checkAlternativeJRE(myConfiguration);
|
||||
ProgramParametersUtil.checkWorkingDirectoryExist(myConfiguration, myConfiguration.getProject(), myConfiguration.getConfigurationModule().getModule());
|
||||
}
|
||||
|
||||
public SourceScope getSourceScope() {
|
||||
return SourceScope.modulesWithDependencies(myConfiguration.getModules());
|
||||
}
|
||||
|
||||
protected void initialize() throws ExecutionException {
|
||||
JavaParametersUtil.configureConfiguration(myJavaParameters, myConfiguration);
|
||||
myJavaParameters.setMainClass(JUnitConfiguration.JUNIT_START_CLASS);
|
||||
final Module module = myConfiguration.getConfigurationModule().getModule();
|
||||
if (myJavaParameters.getJdk() == null){
|
||||
myJavaParameters.setJdk(module != null
|
||||
? ModuleRootManager.getInstance(module).getSdk()
|
||||
: ProjectRootManager.getInstance(myProject).getProjectSdk());
|
||||
}
|
||||
|
||||
myJavaParameters.getClassPath().add(JavaSdkUtil.getIdeaRtJarPath());
|
||||
myJavaParameters.getClassPath().add(PathUtil.getJarPathForClass(JUnitStarter.class));
|
||||
myJavaParameters.getProgramParametersList().add(JUnitStarter.IDE_VERSION + JUnitStarter.VERSION);
|
||||
for (RunConfigurationExtension ext : Extensions.getExtensions(RunConfigurationExtension.EP_NAME)) {
|
||||
ext.updateJavaParameters(myConfiguration, myJavaParameters, getRunnerSettings());
|
||||
}
|
||||
|
||||
final Object[] listeners = Extensions.getExtensions(IDEAJUnitListener.EP_NAME);
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
for (final Object listener : listeners) {
|
||||
boolean enabled = true;
|
||||
for (RunConfigurationExtension ext : Extensions.getExtensions(RunConfigurationExtension.EP_NAME)) {
|
||||
if (ext.isListenerDisabled(myConfiguration, listener, getRunnerSettings())) {
|
||||
enabled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (enabled) {
|
||||
final Class classListener = listener.getClass();
|
||||
buf.append(classListener.getName()).append("\n");
|
||||
myJavaParameters.getClassPath().add(PathUtil.getJarPathForClass(classListener));
|
||||
}
|
||||
}
|
||||
if (buf.length() > 0) {
|
||||
try {
|
||||
myListenersFile = FileUtil.createTempFile("junit_listeners_", "");
|
||||
myListenersFile.deleteOnExit();
|
||||
myJavaParameters.getProgramParametersList().add("@@" + myListenersFile.getPath());
|
||||
FileUtil.writeToFile(myListenersFile, buf.toString().getBytes());
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaParameters getJavaParameters() throws ExecutionException {
|
||||
if (myJavaParameters == null) {
|
||||
myJavaParameters = new JavaParameters();
|
||||
initialize();
|
||||
final Module module = myConfiguration.getConfigurationModule().getModule();
|
||||
final Object[] patchers = Extensions.getExtensions(ExtensionPoints.JUNIT_PATCHER);
|
||||
for (Object patcher : patchers) {
|
||||
((JUnitPatcher)patcher).patchJavaParameters(module, myJavaParameters);
|
||||
}
|
||||
}
|
||||
return myJavaParameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecutionResult execute(final Executor executor, @NotNull final ProgramRunner runner) throws ExecutionException {
|
||||
final JUnitProcessHandler handler = createHandler(executor);
|
||||
final RunnerSettings runnerSettings = getRunnerSettings();
|
||||
JavaRunConfigurationExtensionManager.getInstance().attachExtensionsToProcess(myConfiguration, handler, runnerSettings);
|
||||
final TestProxy unboundOutputRoot = new TestProxy(new RootTestInfo());
|
||||
final JUnitConsoleProperties consoleProperties = new JUnitConsoleProperties(myConfiguration, executor);
|
||||
final JUnitTreeConsoleView consoleView = new JUnitTreeConsoleView(consoleProperties, runnerSettings, getConfigurationSettings(), unboundOutputRoot);
|
||||
consoleView.initUI();
|
||||
consoleView.attachToProcess(handler);
|
||||
unboundOutputRoot.setPrinter(consoleView.getPrinter());
|
||||
Disposer.register(consoleView, unboundOutputRoot);
|
||||
final TestsPacketsReceiver packetsReceiver = new TestsPacketsReceiver(consoleView, unboundOutputRoot) {
|
||||
@Override
|
||||
public void notifyStart(TestProxy root) {
|
||||
if (!isRunning()) return;
|
||||
super.notifyStart(root);
|
||||
unboundOutputRoot.addChild(root);
|
||||
if (myConfiguration.isSaveOutputToFile()) {
|
||||
unboundOutputRoot.setOutputFilePath(myConfiguration.getOutputFilePath());
|
||||
}
|
||||
final JUnitRunningModel model = getModel();
|
||||
if (model != null) {
|
||||
handler.getOut().setDispatchListener(model.getNotifier());
|
||||
Disposer.register(model, new Disposable() {
|
||||
@Override
|
||||
public void dispose() {
|
||||
handler.getOut().setDispatchListener(DispatchListener.DEAF);
|
||||
}
|
||||
});
|
||||
consoleView.attachToModel(model);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
final DeferredActionsQueue queue = new DeferredActionsQueueImpl();
|
||||
handler.getOut().setPacketDispatcher(packetsReceiver, queue);
|
||||
handler.getErr().setPacketDispatcher(packetsReceiver, queue);
|
||||
|
||||
handler.addProcessListener(new ProcessAdapter() {
|
||||
@Override
|
||||
public void processTerminated(ProcessEvent event) {
|
||||
handler.removeProcessListener(this);
|
||||
if (myTempFile != null) {
|
||||
FileUtil.delete(myTempFile);
|
||||
}
|
||||
if (myListenersFile != null) {
|
||||
FileUtil.delete(myListenersFile);
|
||||
}
|
||||
IJSwingUtilities.invoke(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
unboundOutputRoot.flush();
|
||||
packetsReceiver.checkTerminated();
|
||||
final JUnitRunningModel model = packetsReceiver.getModel();
|
||||
notifyByBalloon(model, consoleProperties);
|
||||
}
|
||||
finally {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
Disposer.dispose(consoleView);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextAvailable(final ProcessEvent event, final Key outputType) {
|
||||
final String text = event.getText();
|
||||
final ConsoleViewContentType consoleViewType = ConsoleViewContentType.getConsoleViewType(outputType);
|
||||
final Printable printable = new Printable() {
|
||||
@Override
|
||||
public void printOn(final Printer printer) {
|
||||
printer.print(text, consoleViewType);
|
||||
}
|
||||
};
|
||||
final Extractor extractor;
|
||||
if (consoleViewType == ConsoleViewContentType.ERROR_OUTPUT ||
|
||||
consoleViewType == ConsoleViewContentType.SYSTEM_OUTPUT) {
|
||||
extractor = handler.getErr();
|
||||
}
|
||||
else {
|
||||
extractor = handler.getOut();
|
||||
}
|
||||
extractor.getEventsDispatcher().processOutput(printable);
|
||||
}
|
||||
});
|
||||
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
return new DefaultExecutionResult(null, handler);
|
||||
}
|
||||
|
||||
final RerunFailedTestsAction rerunFailedTestsAction = new RerunFailedTestsAction(consoleView);
|
||||
rerunFailedTestsAction.init(consoleProperties, myEnvironment);
|
||||
rerunFailedTestsAction.setModelProvider(new Getter<TestFrameworkRunningModel>() {
|
||||
@Override
|
||||
public TestFrameworkRunningModel get() {
|
||||
return packetsReceiver.getModel();
|
||||
}
|
||||
});
|
||||
|
||||
final DefaultExecutionResult result = new DefaultExecutionResult(consoleView, handler);
|
||||
result.setRestartActions(rerunFailedTestsAction);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void notifyByBalloon(JUnitRunningModel model, JUnitConsoleProperties consoleProperties) {
|
||||
TestsUIUtil.notifyByBalloon(myProject, model != null ? model.getRoot() : null, consoleProperties);
|
||||
}
|
||||
|
||||
protected JUnitProcessHandler createHandler(Executor executor) throws ExecutionException {
|
||||
appendForkInfo(executor);
|
||||
return JUnitProcessHandler.runCommandLine(CommandLineBuilder.createFromJavaParameters(myJavaParameters, myProject, true));
|
||||
}
|
||||
|
||||
private void appendForkInfo(Executor executor) throws ExecutionException {
|
||||
final String forkMode = myConfiguration.getForkMode();
|
||||
if (Comparing.strEqual(forkMode, "none")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (getRunnerSettings().getData() != null) {
|
||||
final String actionName = executor.getActionName();
|
||||
throw new CantRunException(actionName + " is disabled in fork mode.<br/>Please change fork mode to <none> to " + actionName.toLowerCase() + ".");
|
||||
}
|
||||
|
||||
final JavaParameters javaParameters = getJavaParameters();
|
||||
final Sdk jdk = javaParameters.getJdk();
|
||||
if (jdk == null) {
|
||||
throw new ExecutionException(ExecutionBundle.message("run.configuration.error.no.jdk.specified"));
|
||||
}
|
||||
|
||||
try {
|
||||
final File tempFile = FileUtil.createTempFile("command.line", "", true);
|
||||
final PrintWriter writer = new PrintWriter(tempFile, "UTF-8");
|
||||
try {
|
||||
writer.println(((JavaSdkType)jdk.getSdkType()).getVMExecutablePath(jdk));
|
||||
for (String vmParameter : javaParameters.getVMParametersList().getList()) {
|
||||
writer.println(vmParameter);
|
||||
}
|
||||
writer.println("-classpath");
|
||||
writer.println(javaParameters.getClassPath().getPathsString());
|
||||
}
|
||||
finally {
|
||||
writer.close();
|
||||
}
|
||||
|
||||
myJavaParameters.getProgramParametersList().add("@@@" + forkMode + ',' + tempFile.getAbsolutePath());
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected <T> void addClassesListToJavaParameters(Collection<? extends T> elements, Function<T, String> nameFunction, String packageName,
|
||||
boolean createTempFile,
|
||||
boolean junit4) {
|
||||
try {
|
||||
if (createTempFile) {
|
||||
myTempFile = FileUtil.createTempFile("idea_junit", ".tmp");
|
||||
myTempFile.deleteOnExit();
|
||||
myJavaParameters.getProgramParametersList().add("@" + myTempFile.getAbsolutePath());
|
||||
}
|
||||
|
||||
final PrintWriter writer = new PrintWriter(myTempFile, "UTF-8");
|
||||
try {
|
||||
writer.println(packageName);
|
||||
final List<String> testNames = new ArrayList<String>();
|
||||
for (final T element : elements) {
|
||||
final String name = nameFunction.fun(element);
|
||||
if (name == null) {
|
||||
LOG.error("invalid element " + element);
|
||||
return;
|
||||
}
|
||||
testNames.add(name);
|
||||
}
|
||||
Collections.sort(testNames); //sort tests in FQN order
|
||||
for (String testName : testNames) {
|
||||
writer.println(testName);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
myJavaParameters = null;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-4
@@ -24,17 +24,16 @@ import com.intellij.execution.junit.JUnitConfiguration;
|
||||
import com.intellij.execution.junit.TestMethods;
|
||||
import com.intellij.execution.runners.ExecutionEnvironment;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.ui.ComponentContainer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* @author Alexey
|
||||
*/
|
||||
public class RerunFailedTestsAction extends AbstractRerunFailedTestsAction {
|
||||
|
||||
public RerunFailedTestsAction(JComponent parent) {
|
||||
super(parent);
|
||||
public RerunFailedTestsAction(@NotNull ComponentContainer componentContainer) {
|
||||
super(componentContainer);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+390
-390
@@ -1,390 +1,390 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: amrk
|
||||
* Date: Jul 2, 2005
|
||||
* Time: 12:22:07 AM
|
||||
*/
|
||||
package com.theoryinpractice.testng.configuration;
|
||||
|
||||
import com.intellij.ExtensionPoints;
|
||||
import com.intellij.debugger.engine.DebuggerUtils;
|
||||
import com.intellij.execution.*;
|
||||
import com.intellij.execution.configurations.*;
|
||||
import com.intellij.execution.process.OSProcessHandler;
|
||||
import com.intellij.execution.process.ProcessAdapter;
|
||||
import com.intellij.execution.process.ProcessEvent;
|
||||
import com.intellij.execution.runners.ExecutionEnvironment;
|
||||
import com.intellij.execution.runners.ProgramRunner;
|
||||
import com.intellij.execution.testframework.*;
|
||||
import com.intellij.execution.ui.ConsoleViewContentType;
|
||||
import com.intellij.execution.util.JavaParametersUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.module.LanguageLevelUtil;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.progress.impl.BackgroundableProcessIndicator;
|
||||
import com.intellij.openapi.progress.impl.ProgressManagerImpl;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.ex.JavaSdkUtil;
|
||||
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Getter;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.wm.ToolWindowId;
|
||||
import com.intellij.openapi.wm.ToolWindowManager;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.JavaPsiFacade;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.util.PathUtil;
|
||||
import com.intellij.util.net.NetUtils;
|
||||
import com.theoryinpractice.testng.model.*;
|
||||
import com.theoryinpractice.testng.ui.TestNGConsoleView;
|
||||
import com.theoryinpractice.testng.ui.TestNGResults;
|
||||
import com.theoryinpractice.testng.ui.actions.RerunFailedTestsAction;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.testng.CommandLineArgs;
|
||||
import org.testng.IDEATestNGListener;
|
||||
import org.testng.RemoteTestNGStarter;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.remote.RemoteArgs;
|
||||
import org.testng.remote.RemoteTestNG;
|
||||
import org.testng.remote.strprotocol.MessageHelper;
|
||||
import org.testng.remote.strprotocol.SerializedMessageSender;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
public class TestNGRunnableState extends JavaCommandLineState {
|
||||
private static final Logger LOG = Logger.getInstance("TestNG Runner");
|
||||
private final ConfigurationPerRunnerSettings myConfigurationPerRunnerSettings;
|
||||
private final TestNGConfiguration config;
|
||||
private final RunnerSettings runnerSettings;
|
||||
protected final IDEARemoteTestRunnerClient client;
|
||||
private int port;
|
||||
private String debugPort;
|
||||
private File myTempFile;
|
||||
private BackgroundableProcessIndicator mySearchForTestIndicator;
|
||||
private ServerSocket myServerSocket;
|
||||
|
||||
public TestNGRunnableState(ExecutionEnvironment environment, TestNGConfiguration config) {
|
||||
super(environment);
|
||||
this.runnerSettings = environment.getRunnerSettings();
|
||||
myConfigurationPerRunnerSettings = environment.getConfigurationSettings();
|
||||
this.config = config;
|
||||
//TODO need to narrow this down a bit
|
||||
//setModulesToCompile(ModuleManager.getInstance(config.getProject()).getModules());
|
||||
client = new IDEARemoteTestRunnerClient();
|
||||
// Want debugging?
|
||||
if (runnerSettings.getData() instanceof DebuggingRunnerData) {
|
||||
DebuggingRunnerData debuggingRunnerData = ((DebuggingRunnerData)runnerSettings.getData());
|
||||
debugPort = debuggingRunnerData.getDebugPort();
|
||||
if (debugPort.length() == 0) {
|
||||
try {
|
||||
debugPort = DebuggerUtils.getInstance().findAvailableDebugAddress(true);
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
debuggingRunnerData.setDebugPort(debugPort);
|
||||
}
|
||||
debuggingRunnerData.setLocal(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecutionResult execute(@NotNull final Executor executor, @NotNull final ProgramRunner runner) throws ExecutionException {
|
||||
OSProcessHandler processHandler = startProcess();
|
||||
final TreeRootNode unboundOutputRoot = new TreeRootNode();
|
||||
final TestNGConsoleView console = new TestNGConsoleView(config, runnerSettings, myConfigurationPerRunnerSettings, unboundOutputRoot,
|
||||
executor);
|
||||
console.initUI();
|
||||
unboundOutputRoot.setPrinter(console.getPrinter());
|
||||
Disposer.register(console, unboundOutputRoot);
|
||||
JavaRunConfigurationExtensionManager.getInstance().attachExtensionsToProcess(config, processHandler, runnerSettings);
|
||||
final SearchingForTestsTask task = createSearchingForTestsTask(myServerSocket, config, myTempFile);
|
||||
processHandler.addProcessListener(new ProcessAdapter() {
|
||||
@Override
|
||||
public void processTerminated(final ProcessEvent event) {
|
||||
unboundOutputRoot.flush();
|
||||
|
||||
if (mySearchForTestIndicator != null && !mySearchForTestIndicator.isCanceled()) {
|
||||
task.finish();
|
||||
}
|
||||
|
||||
final Runnable notificationRunnable = new Runnable() {
|
||||
public void run() {
|
||||
final Project project = config.getProject();
|
||||
if (project.isDisposed()) return;
|
||||
|
||||
final TestConsoleProperties consoleProperties = console.getProperties();
|
||||
if (consoleProperties == null) return;
|
||||
final String testRunDebugId = consoleProperties.isDebug() ? ToolWindowId.DEBUG : ToolWindowId.RUN;
|
||||
final TestNGResults resultsView = console.getResultsView();
|
||||
final ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(project);
|
||||
if (!Comparing.strEqual(toolWindowManager.getActiveToolWindowId(), testRunDebugId)) {
|
||||
final MessageType type = resultsView == null || resultsView.getStatus() == MessageHelper.SKIPPED_TEST
|
||||
? MessageType.WARNING
|
||||
: (resultsView.getStatus() == MessageHelper.FAILED_TEST
|
||||
? MessageType.ERROR
|
||||
: MessageType.INFO);
|
||||
final String message = resultsView == null ? "Tests were not started" : resultsView.getStatusLine();
|
||||
toolWindowManager.notifyByBalloon(testRunDebugId, type, message, null, null);
|
||||
TestsUIUtil.NOTIFICATION_GROUP.createNotification(message, type).notify(project);
|
||||
}
|
||||
}
|
||||
};
|
||||
SwingUtilities.invokeLater(notificationRunnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startNotified(final ProcessEvent event) {
|
||||
TestNGRemoteListener listener = new TestNGRemoteListener(console, unboundOutputRoot);
|
||||
if (config.isSaveOutputToFile()) {
|
||||
unboundOutputRoot.setOutputFilePath(config.getOutputFilePath());
|
||||
}
|
||||
client.prepareListening(listener, port);
|
||||
mySearchForTestIndicator = new BackgroundableProcessIndicator(task);
|
||||
ProgressManagerImpl.runProcessWithProgressAsynchronously(task, mySearchForTestIndicator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processWillTerminate(ProcessEvent event, boolean willBeDestroyed) {
|
||||
final TestNGResults resultsView = console.getResultsView();
|
||||
if (resultsView != null) {
|
||||
resultsView.finish();
|
||||
}
|
||||
}
|
||||
|
||||
private int myInsertIndex = 0;
|
||||
@Override
|
||||
public void onTextAvailable(final ProcessEvent event, final Key outputType) {
|
||||
final TestProxy currentTest = console.getCurrentTest();
|
||||
final String text = event.getText();
|
||||
final ConsoleViewContentType consoleViewType = ConsoleViewContentType.getConsoleViewType(outputType);
|
||||
final Printable printable = new Printable() {
|
||||
public void printOn(final Printer printer) {
|
||||
printer.print(text, consoleViewType);
|
||||
}
|
||||
};
|
||||
if (currentTest != null) {
|
||||
currentTest.addLast(printable);
|
||||
}
|
||||
else {
|
||||
unboundOutputRoot.insert(printable, myInsertIndex);
|
||||
}
|
||||
myInsertIndex++;
|
||||
}
|
||||
});
|
||||
console.attachToProcess(processHandler);
|
||||
|
||||
RerunFailedTestsAction rerunFailedTestsAction = new RerunFailedTestsAction(console.getComponent());
|
||||
rerunFailedTestsAction.init(console.getProperties(), getEnvironment());
|
||||
rerunFailedTestsAction.setModelProvider(new Getter<TestFrameworkRunningModel>() {
|
||||
public TestFrameworkRunningModel get() {
|
||||
return console.getResultsView();
|
||||
}
|
||||
});
|
||||
|
||||
final DefaultExecutionResult result = new DefaultExecutionResult(console, processHandler);
|
||||
result.setRestartActions(rerunFailedTestsAction);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JavaParameters createJavaParameters() throws ExecutionException {
|
||||
final Project project = config.getProject();
|
||||
final JavaParameters javaParameters = new JavaParameters();
|
||||
javaParameters.setupEnvs(config.getPersistantData().getEnvs(), config.getPersistantData().PASS_PARENT_ENVS);
|
||||
javaParameters.setMainClass("org.testng.RemoteTestNGStarter");
|
||||
javaParameters.setWorkingDirectory(config.getWorkingDirectory());
|
||||
javaParameters.getClassPath().add(PathUtil.getJarPathForClass(RemoteTestNGStarter.class));
|
||||
|
||||
//the next few lines are awkward for a reason, using compareTo for some reason causes a JVM class verification error!
|
||||
Module module = config.getConfigurationModule().getModule();
|
||||
LanguageLevel effectiveLanguageLevel = module == null
|
||||
? LanguageLevelProjectExtension.getInstance(project).getLanguageLevel()
|
||||
: LanguageLevelUtil.getEffectiveLanguageLevel(module);
|
||||
final boolean is15 = effectiveLanguageLevel != LanguageLevel.JDK_1_4 && effectiveLanguageLevel != LanguageLevel.JDK_1_3;
|
||||
|
||||
LOG.info("Language level is " + effectiveLanguageLevel.toString());
|
||||
LOG.info("is15 is " + is15);
|
||||
final String pathToBundledJar = PathUtil.getJarPathForClass(AfterClass.class);
|
||||
|
||||
// Configure rest of jars
|
||||
JavaParametersUtil.configureConfiguration(javaParameters, config);
|
||||
Sdk jdk = module == null ? ProjectRootManager.getInstance(project).getProjectSdk() : ModuleRootManager.getInstance(module).getSdk();
|
||||
javaParameters.setJdk(jdk);
|
||||
final Object[] patchers = Extensions.getExtensions(ExtensionPoints.JUNIT_PATCHER);
|
||||
for (Object patcher : patchers) {
|
||||
((JUnitPatcher)patcher).patchJavaParameters(module, javaParameters);
|
||||
}
|
||||
JavaSdkUtil.addRtJar(javaParameters.getClassPath());
|
||||
|
||||
// Append coverage parameters if appropriate
|
||||
for (RunConfigurationExtension ext : Extensions.getExtensions(RunConfigurationExtension.EP_NAME)) {
|
||||
ext.updateJavaParameters(config, javaParameters, getRunnerSettings());
|
||||
}
|
||||
|
||||
LOG.info("Test scope is: " + config.getPersistantData().getScope());
|
||||
if (config.getPersistantData().getScope() == TestSearchScope.WHOLE_PROJECT) {
|
||||
LOG.info("Configuring for whole project");
|
||||
JavaParametersUtil.configureProject(config.getProject(), javaParameters, JavaParameters.JDK_AND_CLASSES_AND_TESTS,
|
||||
config.ALTERNATIVE_JRE_PATH_ENABLED ? config.ALTERNATIVE_JRE_PATH : null);
|
||||
}
|
||||
else {
|
||||
LOG.info("Configuring for module:" + config.getConfigurationModule().getModuleName());
|
||||
JavaParametersUtil.configureModule(config.getConfigurationModule(), javaParameters, JavaParameters.JDK_AND_CLASSES_AND_TESTS,
|
||||
config.ALTERNATIVE_JRE_PATH_ENABLED ? config.ALTERNATIVE_JRE_PATH : null);
|
||||
}
|
||||
|
||||
javaParameters.getClassPath().add(pathToBundledJar);
|
||||
|
||||
try {
|
||||
port = NetUtils.findAvailableSocketPort();
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new ExecutionException("Unable to bind to port " + port, e);
|
||||
}
|
||||
|
||||
final TestData data = config.getPersistantData();
|
||||
|
||||
javaParameters.getProgramParametersList().add(supportSerializationProtocol(config) ? RemoteArgs.PORT : CommandLineArgs.PORT, String.valueOf(port));
|
||||
|
||||
if (data.getOutputDirectory() != null && !"".equals(data.getOutputDirectory())) {
|
||||
javaParameters.getProgramParametersList().add(CommandLineArgs.OUTPUT_DIRECTORY, data.getOutputDirectory());
|
||||
}
|
||||
|
||||
javaParameters.getProgramParametersList().add(CommandLineArgs.USE_DEFAULT_LISTENERS, String.valueOf(data.USE_DEFAULT_REPORTERS));
|
||||
|
||||
@NonNls final StringBuilder buf = new StringBuilder();
|
||||
if (data.TEST_LISTENERS != null && !data.TEST_LISTENERS.isEmpty()) {
|
||||
buf.append(StringUtil.join(data.TEST_LISTENERS, ";"));
|
||||
}
|
||||
|
||||
for (Object o : Extensions.getExtensions(IDEATestNGListener.EP_NAME)) {
|
||||
boolean enabled = true;
|
||||
for (RunConfigurationExtension extension : Extensions.getExtensions(RunConfigurationExtension.EP_NAME)) {
|
||||
if (extension.isListenerDisabled(config, o, getRunnerSettings())) {
|
||||
enabled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (enabled) {
|
||||
if (buf.length() > 0) buf.append(";");
|
||||
buf.append(o.getClass().getName());
|
||||
javaParameters.getClassPath().add(PathUtil.getJarPathForClass(o.getClass()));
|
||||
}
|
||||
}
|
||||
if (buf.length() > 0) javaParameters.getProgramParametersList().add(CommandLineArgs.LISTENER, buf.toString());
|
||||
|
||||
/* // Always include the source paths - just makes things easier :)
|
||||
VirtualFile[] sources;
|
||||
if ((data.getScope() == TestSearchScope.WHOLE_PROJECT && TestType.PACKAGE.getType().equals(data.TEST_OBJECT)) || module == null) {
|
||||
sources = ProjectRootManager.getInstance(project).getContentSourceRoots();
|
||||
}
|
||||
else {
|
||||
sources = ModuleRootManager.getInstance(module).getSourceRoots();
|
||||
}
|
||||
|
||||
if (sources.length > 0) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
for (int i = 0; i < sources.length; i++) {
|
||||
VirtualFile source = sources[i];
|
||||
sb.append(source.getPath());
|
||||
if (i < sources.length - 1) {
|
||||
sb.append(';');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
javaParameters.getProgramParametersList().add(TestNGCommandLineArgs.SRC_COMMAND_OPT, sb.toString());
|
||||
}*/
|
||||
try {
|
||||
myServerSocket = new ServerSocket(0, 0, InetAddress.getByName("127.0.0.1"));
|
||||
javaParameters.getProgramParametersList().add("-socket" + myServerSocket.getLocalPort());
|
||||
myTempFile = FileUtil.createTempFile("idea_testng", ".tmp");
|
||||
myTempFile.deleteOnExit();
|
||||
javaParameters.getProgramParametersList().add("-temp", myTempFile.getAbsolutePath());
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
// Configure for debugging
|
||||
if (runnerSettings.getData() instanceof DebuggingRunnerData) {
|
||||
ParametersList params = javaParameters.getVMParametersList();
|
||||
|
||||
String hostname = "localhost";
|
||||
try {
|
||||
hostname = InetAddress.getLocalHost().getHostName();
|
||||
}
|
||||
catch (UnknownHostException e) {
|
||||
}
|
||||
params.add("-Xdebug");
|
||||
params.add("-Xrunjdwp:transport=dt_socket,address=" + hostname + ':' + debugPort + ",suspend=y,server=n");
|
||||
// params.add(debugPort);
|
||||
}
|
||||
|
||||
return javaParameters;
|
||||
}
|
||||
|
||||
protected SearchingForTestsTask createSearchingForTestsTask(ServerSocket serverSocket,
|
||||
final TestNGConfiguration config,
|
||||
final File tempFile) {
|
||||
return new SearchingForTestsTask(serverSocket, config, tempFile, client);
|
||||
}
|
||||
|
||||
public static boolean supportSerializationProtocol(TestNGConfiguration config) {
|
||||
final Project project = config.getProject();
|
||||
final GlobalSearchScope scopeToDetermineTestngIn;
|
||||
if (config.getPersistantData().getScope() == TestSearchScope.WHOLE_PROJECT) {
|
||||
scopeToDetermineTestngIn = GlobalSearchScope.allScope(project);
|
||||
}
|
||||
else {
|
||||
scopeToDetermineTestngIn = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(config.getConfigurationModule().getModule());
|
||||
}
|
||||
|
||||
final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
|
||||
final PsiClass aClass = facade.findClass(SerializedMessageSender.class.getName(), scopeToDetermineTestngIn);
|
||||
if (aClass == null) return false;
|
||||
|
||||
final PsiClass[] starters = facade.findClasses(RemoteTestNG.class.getName(), scopeToDetermineTestngIn);
|
||||
for (PsiClass starter : starters) {
|
||||
if (starter.findFieldByName("m_serPort", false) == null) {
|
||||
LOG.info("Multiple TestNG versions found");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return Registry.is("testng.serialized.protocol.enabled") && !TestNGVersionChecker.isVersionIncompatible(project, scopeToDetermineTestngIn);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: amrk
|
||||
* Date: Jul 2, 2005
|
||||
* Time: 12:22:07 AM
|
||||
*/
|
||||
package com.theoryinpractice.testng.configuration;
|
||||
|
||||
import com.intellij.ExtensionPoints;
|
||||
import com.intellij.debugger.engine.DebuggerUtils;
|
||||
import com.intellij.execution.*;
|
||||
import com.intellij.execution.configurations.*;
|
||||
import com.intellij.execution.process.OSProcessHandler;
|
||||
import com.intellij.execution.process.ProcessAdapter;
|
||||
import com.intellij.execution.process.ProcessEvent;
|
||||
import com.intellij.execution.runners.ExecutionEnvironment;
|
||||
import com.intellij.execution.runners.ProgramRunner;
|
||||
import com.intellij.execution.testframework.*;
|
||||
import com.intellij.execution.ui.ConsoleViewContentType;
|
||||
import com.intellij.execution.util.JavaParametersUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.module.LanguageLevelUtil;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.progress.impl.BackgroundableProcessIndicator;
|
||||
import com.intellij.openapi.progress.impl.ProgressManagerImpl;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.ex.JavaSdkUtil;
|
||||
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Getter;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.wm.ToolWindowId;
|
||||
import com.intellij.openapi.wm.ToolWindowManager;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.JavaPsiFacade;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.util.PathUtil;
|
||||
import com.intellij.util.net.NetUtils;
|
||||
import com.theoryinpractice.testng.model.*;
|
||||
import com.theoryinpractice.testng.ui.TestNGConsoleView;
|
||||
import com.theoryinpractice.testng.ui.TestNGResults;
|
||||
import com.theoryinpractice.testng.ui.actions.RerunFailedTestsAction;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.testng.CommandLineArgs;
|
||||
import org.testng.IDEATestNGListener;
|
||||
import org.testng.RemoteTestNGStarter;
|
||||
import org.testng.annotations.AfterClass;
|
||||
import org.testng.remote.RemoteArgs;
|
||||
import org.testng.remote.RemoteTestNG;
|
||||
import org.testng.remote.strprotocol.MessageHelper;
|
||||
import org.testng.remote.strprotocol.SerializedMessageSender;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
public class TestNGRunnableState extends JavaCommandLineState {
|
||||
private static final Logger LOG = Logger.getInstance("TestNG Runner");
|
||||
private final ConfigurationPerRunnerSettings myConfigurationPerRunnerSettings;
|
||||
private final TestNGConfiguration config;
|
||||
private final RunnerSettings runnerSettings;
|
||||
protected final IDEARemoteTestRunnerClient client;
|
||||
private int port;
|
||||
private String debugPort;
|
||||
private File myTempFile;
|
||||
private BackgroundableProcessIndicator mySearchForTestIndicator;
|
||||
private ServerSocket myServerSocket;
|
||||
|
||||
public TestNGRunnableState(ExecutionEnvironment environment, TestNGConfiguration config) {
|
||||
super(environment);
|
||||
this.runnerSettings = environment.getRunnerSettings();
|
||||
myConfigurationPerRunnerSettings = environment.getConfigurationSettings();
|
||||
this.config = config;
|
||||
//TODO need to narrow this down a bit
|
||||
//setModulesToCompile(ModuleManager.getInstance(config.getProject()).getModules());
|
||||
client = new IDEARemoteTestRunnerClient();
|
||||
// Want debugging?
|
||||
if (runnerSettings.getData() instanceof DebuggingRunnerData) {
|
||||
DebuggingRunnerData debuggingRunnerData = ((DebuggingRunnerData)runnerSettings.getData());
|
||||
debugPort = debuggingRunnerData.getDebugPort();
|
||||
if (debugPort.length() == 0) {
|
||||
try {
|
||||
debugPort = DebuggerUtils.getInstance().findAvailableDebugAddress(true);
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
debuggingRunnerData.setDebugPort(debugPort);
|
||||
}
|
||||
debuggingRunnerData.setLocal(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecutionResult execute(@NotNull final Executor executor, @NotNull final ProgramRunner runner) throws ExecutionException {
|
||||
OSProcessHandler processHandler = startProcess();
|
||||
final TreeRootNode unboundOutputRoot = new TreeRootNode();
|
||||
final TestNGConsoleView console = new TestNGConsoleView(config, runnerSettings, myConfigurationPerRunnerSettings, unboundOutputRoot,
|
||||
executor);
|
||||
console.initUI();
|
||||
unboundOutputRoot.setPrinter(console.getPrinter());
|
||||
Disposer.register(console, unboundOutputRoot);
|
||||
JavaRunConfigurationExtensionManager.getInstance().attachExtensionsToProcess(config, processHandler, runnerSettings);
|
||||
final SearchingForTestsTask task = createSearchingForTestsTask(myServerSocket, config, myTempFile);
|
||||
processHandler.addProcessListener(new ProcessAdapter() {
|
||||
@Override
|
||||
public void processTerminated(final ProcessEvent event) {
|
||||
unboundOutputRoot.flush();
|
||||
|
||||
if (mySearchForTestIndicator != null && !mySearchForTestIndicator.isCanceled()) {
|
||||
task.finish();
|
||||
}
|
||||
|
||||
final Runnable notificationRunnable = new Runnable() {
|
||||
public void run() {
|
||||
final Project project = config.getProject();
|
||||
if (project.isDisposed()) return;
|
||||
|
||||
final TestConsoleProperties consoleProperties = console.getProperties();
|
||||
if (consoleProperties == null) return;
|
||||
final String testRunDebugId = consoleProperties.isDebug() ? ToolWindowId.DEBUG : ToolWindowId.RUN;
|
||||
final TestNGResults resultsView = console.getResultsView();
|
||||
final ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(project);
|
||||
if (!Comparing.strEqual(toolWindowManager.getActiveToolWindowId(), testRunDebugId)) {
|
||||
final MessageType type = resultsView == null || resultsView.getStatus() == MessageHelper.SKIPPED_TEST
|
||||
? MessageType.WARNING
|
||||
: (resultsView.getStatus() == MessageHelper.FAILED_TEST
|
||||
? MessageType.ERROR
|
||||
: MessageType.INFO);
|
||||
final String message = resultsView == null ? "Tests were not started" : resultsView.getStatusLine();
|
||||
toolWindowManager.notifyByBalloon(testRunDebugId, type, message, null, null);
|
||||
TestsUIUtil.NOTIFICATION_GROUP.createNotification(message, type).notify(project);
|
||||
}
|
||||
}
|
||||
};
|
||||
SwingUtilities.invokeLater(notificationRunnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startNotified(final ProcessEvent event) {
|
||||
TestNGRemoteListener listener = new TestNGRemoteListener(console, unboundOutputRoot);
|
||||
if (config.isSaveOutputToFile()) {
|
||||
unboundOutputRoot.setOutputFilePath(config.getOutputFilePath());
|
||||
}
|
||||
client.prepareListening(listener, port);
|
||||
mySearchForTestIndicator = new BackgroundableProcessIndicator(task);
|
||||
ProgressManagerImpl.runProcessWithProgressAsynchronously(task, mySearchForTestIndicator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processWillTerminate(ProcessEvent event, boolean willBeDestroyed) {
|
||||
final TestNGResults resultsView = console.getResultsView();
|
||||
if (resultsView != null) {
|
||||
resultsView.finish();
|
||||
}
|
||||
}
|
||||
|
||||
private int myInsertIndex = 0;
|
||||
@Override
|
||||
public void onTextAvailable(final ProcessEvent event, final Key outputType) {
|
||||
final TestProxy currentTest = console.getCurrentTest();
|
||||
final String text = event.getText();
|
||||
final ConsoleViewContentType consoleViewType = ConsoleViewContentType.getConsoleViewType(outputType);
|
||||
final Printable printable = new Printable() {
|
||||
public void printOn(final Printer printer) {
|
||||
printer.print(text, consoleViewType);
|
||||
}
|
||||
};
|
||||
if (currentTest != null) {
|
||||
currentTest.addLast(printable);
|
||||
}
|
||||
else {
|
||||
unboundOutputRoot.insert(printable, myInsertIndex);
|
||||
}
|
||||
myInsertIndex++;
|
||||
}
|
||||
});
|
||||
console.attachToProcess(processHandler);
|
||||
|
||||
RerunFailedTestsAction rerunFailedTestsAction = new RerunFailedTestsAction(console);
|
||||
rerunFailedTestsAction.init(console.getProperties(), getEnvironment());
|
||||
rerunFailedTestsAction.setModelProvider(new Getter<TestFrameworkRunningModel>() {
|
||||
public TestFrameworkRunningModel get() {
|
||||
return console.getResultsView();
|
||||
}
|
||||
});
|
||||
|
||||
final DefaultExecutionResult result = new DefaultExecutionResult(console, processHandler);
|
||||
result.setRestartActions(rerunFailedTestsAction);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JavaParameters createJavaParameters() throws ExecutionException {
|
||||
final Project project = config.getProject();
|
||||
final JavaParameters javaParameters = new JavaParameters();
|
||||
javaParameters.setupEnvs(config.getPersistantData().getEnvs(), config.getPersistantData().PASS_PARENT_ENVS);
|
||||
javaParameters.setMainClass("org.testng.RemoteTestNGStarter");
|
||||
javaParameters.setWorkingDirectory(config.getWorkingDirectory());
|
||||
javaParameters.getClassPath().add(PathUtil.getJarPathForClass(RemoteTestNGStarter.class));
|
||||
|
||||
//the next few lines are awkward for a reason, using compareTo for some reason causes a JVM class verification error!
|
||||
Module module = config.getConfigurationModule().getModule();
|
||||
LanguageLevel effectiveLanguageLevel = module == null
|
||||
? LanguageLevelProjectExtension.getInstance(project).getLanguageLevel()
|
||||
: LanguageLevelUtil.getEffectiveLanguageLevel(module);
|
||||
final boolean is15 = effectiveLanguageLevel != LanguageLevel.JDK_1_4 && effectiveLanguageLevel != LanguageLevel.JDK_1_3;
|
||||
|
||||
LOG.info("Language level is " + effectiveLanguageLevel.toString());
|
||||
LOG.info("is15 is " + is15);
|
||||
final String pathToBundledJar = PathUtil.getJarPathForClass(AfterClass.class);
|
||||
|
||||
// Configure rest of jars
|
||||
JavaParametersUtil.configureConfiguration(javaParameters, config);
|
||||
Sdk jdk = module == null ? ProjectRootManager.getInstance(project).getProjectSdk() : ModuleRootManager.getInstance(module).getSdk();
|
||||
javaParameters.setJdk(jdk);
|
||||
final Object[] patchers = Extensions.getExtensions(ExtensionPoints.JUNIT_PATCHER);
|
||||
for (Object patcher : patchers) {
|
||||
((JUnitPatcher)patcher).patchJavaParameters(module, javaParameters);
|
||||
}
|
||||
JavaSdkUtil.addRtJar(javaParameters.getClassPath());
|
||||
|
||||
// Append coverage parameters if appropriate
|
||||
for (RunConfigurationExtension ext : Extensions.getExtensions(RunConfigurationExtension.EP_NAME)) {
|
||||
ext.updateJavaParameters(config, javaParameters, getRunnerSettings());
|
||||
}
|
||||
|
||||
LOG.info("Test scope is: " + config.getPersistantData().getScope());
|
||||
if (config.getPersistantData().getScope() == TestSearchScope.WHOLE_PROJECT) {
|
||||
LOG.info("Configuring for whole project");
|
||||
JavaParametersUtil.configureProject(config.getProject(), javaParameters, JavaParameters.JDK_AND_CLASSES_AND_TESTS,
|
||||
config.ALTERNATIVE_JRE_PATH_ENABLED ? config.ALTERNATIVE_JRE_PATH : null);
|
||||
}
|
||||
else {
|
||||
LOG.info("Configuring for module:" + config.getConfigurationModule().getModuleName());
|
||||
JavaParametersUtil.configureModule(config.getConfigurationModule(), javaParameters, JavaParameters.JDK_AND_CLASSES_AND_TESTS,
|
||||
config.ALTERNATIVE_JRE_PATH_ENABLED ? config.ALTERNATIVE_JRE_PATH : null);
|
||||
}
|
||||
|
||||
javaParameters.getClassPath().add(pathToBundledJar);
|
||||
|
||||
try {
|
||||
port = NetUtils.findAvailableSocketPort();
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new ExecutionException("Unable to bind to port " + port, e);
|
||||
}
|
||||
|
||||
final TestData data = config.getPersistantData();
|
||||
|
||||
javaParameters.getProgramParametersList().add(supportSerializationProtocol(config) ? RemoteArgs.PORT : CommandLineArgs.PORT, String.valueOf(port));
|
||||
|
||||
if (data.getOutputDirectory() != null && !"".equals(data.getOutputDirectory())) {
|
||||
javaParameters.getProgramParametersList().add(CommandLineArgs.OUTPUT_DIRECTORY, data.getOutputDirectory());
|
||||
}
|
||||
|
||||
javaParameters.getProgramParametersList().add(CommandLineArgs.USE_DEFAULT_LISTENERS, String.valueOf(data.USE_DEFAULT_REPORTERS));
|
||||
|
||||
@NonNls final StringBuilder buf = new StringBuilder();
|
||||
if (data.TEST_LISTENERS != null && !data.TEST_LISTENERS.isEmpty()) {
|
||||
buf.append(StringUtil.join(data.TEST_LISTENERS, ";"));
|
||||
}
|
||||
|
||||
for (Object o : Extensions.getExtensions(IDEATestNGListener.EP_NAME)) {
|
||||
boolean enabled = true;
|
||||
for (RunConfigurationExtension extension : Extensions.getExtensions(RunConfigurationExtension.EP_NAME)) {
|
||||
if (extension.isListenerDisabled(config, o, getRunnerSettings())) {
|
||||
enabled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (enabled) {
|
||||
if (buf.length() > 0) buf.append(";");
|
||||
buf.append(o.getClass().getName());
|
||||
javaParameters.getClassPath().add(PathUtil.getJarPathForClass(o.getClass()));
|
||||
}
|
||||
}
|
||||
if (buf.length() > 0) javaParameters.getProgramParametersList().add(CommandLineArgs.LISTENER, buf.toString());
|
||||
|
||||
/* // Always include the source paths - just makes things easier :)
|
||||
VirtualFile[] sources;
|
||||
if ((data.getScope() == TestSearchScope.WHOLE_PROJECT && TestType.PACKAGE.getType().equals(data.TEST_OBJECT)) || module == null) {
|
||||
sources = ProjectRootManager.getInstance(project).getContentSourceRoots();
|
||||
}
|
||||
else {
|
||||
sources = ModuleRootManager.getInstance(module).getSourceRoots();
|
||||
}
|
||||
|
||||
if (sources.length > 0) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
for (int i = 0; i < sources.length; i++) {
|
||||
VirtualFile source = sources[i];
|
||||
sb.append(source.getPath());
|
||||
if (i < sources.length - 1) {
|
||||
sb.append(';');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
javaParameters.getProgramParametersList().add(TestNGCommandLineArgs.SRC_COMMAND_OPT, sb.toString());
|
||||
}*/
|
||||
try {
|
||||
myServerSocket = new ServerSocket(0, 0, InetAddress.getByName("127.0.0.1"));
|
||||
javaParameters.getProgramParametersList().add("-socket" + myServerSocket.getLocalPort());
|
||||
myTempFile = FileUtil.createTempFile("idea_testng", ".tmp");
|
||||
myTempFile.deleteOnExit();
|
||||
javaParameters.getProgramParametersList().add("-temp", myTempFile.getAbsolutePath());
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
// Configure for debugging
|
||||
if (runnerSettings.getData() instanceof DebuggingRunnerData) {
|
||||
ParametersList params = javaParameters.getVMParametersList();
|
||||
|
||||
String hostname = "localhost";
|
||||
try {
|
||||
hostname = InetAddress.getLocalHost().getHostName();
|
||||
}
|
||||
catch (UnknownHostException e) {
|
||||
}
|
||||
params.add("-Xdebug");
|
||||
params.add("-Xrunjdwp:transport=dt_socket,address=" + hostname + ':' + debugPort + ",suspend=y,server=n");
|
||||
// params.add(debugPort);
|
||||
}
|
||||
|
||||
return javaParameters;
|
||||
}
|
||||
|
||||
protected SearchingForTestsTask createSearchingForTestsTask(ServerSocket serverSocket,
|
||||
final TestNGConfiguration config,
|
||||
final File tempFile) {
|
||||
return new SearchingForTestsTask(serverSocket, config, tempFile, client);
|
||||
}
|
||||
|
||||
public static boolean supportSerializationProtocol(TestNGConfiguration config) {
|
||||
final Project project = config.getProject();
|
||||
final GlobalSearchScope scopeToDetermineTestngIn;
|
||||
if (config.getPersistantData().getScope() == TestSearchScope.WHOLE_PROJECT) {
|
||||
scopeToDetermineTestngIn = GlobalSearchScope.allScope(project);
|
||||
}
|
||||
else {
|
||||
scopeToDetermineTestngIn = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(config.getConfigurationModule().getModule());
|
||||
}
|
||||
|
||||
final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
|
||||
final PsiClass aClass = facade.findClass(SerializedMessageSender.class.getName(), scopeToDetermineTestngIn);
|
||||
if (aClass == null) return false;
|
||||
|
||||
final PsiClass[] starters = facade.findClasses(RemoteTestNG.class.getName(), scopeToDetermineTestngIn);
|
||||
for (PsiClass starter : starters) {
|
||||
if (starter.findFieldByName("m_serPort", false) == null) {
|
||||
LOG.info("Multiple TestNG versions found");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return Registry.is("testng.serialized.protocol.enabled") && !TestNGVersionChecker.isVersionIncompatible(project, scopeToDetermineTestngIn);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-3
@@ -10,6 +10,7 @@ import com.intellij.execution.configurations.RunProfileState;
|
||||
import com.intellij.execution.runners.ExecutionEnvironment;
|
||||
import com.intellij.execution.testframework.AbstractTestProxy;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.ui.ComponentContainer;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
@@ -18,7 +19,6 @@ import com.theoryinpractice.testng.configuration.TestNGConfiguration;
|
||||
import com.theoryinpractice.testng.configuration.TestNGRunnableState;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.File;
|
||||
import java.net.ServerSocket;
|
||||
import java.util.ArrayList;
|
||||
@@ -27,8 +27,9 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class RerunFailedTestsAction extends AbstractRerunFailedTestsAction {
|
||||
public RerunFailedTestsAction(JComponent parent) {
|
||||
super(parent);
|
||||
|
||||
public RerunFailedTestsAction(@NotNull ComponentContainer componentContainer) {
|
||||
super(componentContainer);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user