Merge branch 'master' of git@git.labs.intellij.net:idea/community

This commit is contained in:
Kirill Kalishev
2010-05-19 21:20:25 +04:00
18 changed files with 289 additions and 99 deletions
@@ -45,6 +45,7 @@ import javax.swing.*;
import javax.swing.event.ChangeEvent;
import java.awt.*;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.*;
@@ -394,6 +395,9 @@ public abstract class ModuleEditor implements Place.Navigator, Disposable {
}
return result;
}
catch (InvocationTargetException e) {
throw e.getCause();
}
finally {
if (needUpdate) {
updateOrderEntriesInEditors();
@@ -433,6 +437,9 @@ public abstract class ModuleEditor implements Place.Navigator, Disposable {
}
return result;
}
catch (InvocationTargetException e) {
throw e.getCause();
}
finally {
if (needUpdate) {
updateOrderEntriesInEditors();
@@ -450,12 +457,17 @@ public abstract class ModuleEditor implements Place.Navigator, Disposable {
}
public Object invoke(Object object, Method method, Object[] params) throws Throwable {
final Object result = method.invoke(myDelegateLibrary, unwrapParams(params));
if (result instanceof Library.ModifiableModel) {
return Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{Library.ModifiableModel.class},
new LibraryModifiableModelInvocationHandler((Library.ModifiableModel)result));
try {
final Object result = method.invoke(myDelegateLibrary, unwrapParams(params));
if (result instanceof Library.ModifiableModel) {
return Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{Library.ModifiableModel.class},
new LibraryModifiableModelInvocationHandler((Library.ModifiableModel)result));
}
return result;
}
catch (InvocationTargetException e) {
throw e.getCause();
}
return result;
}
public Object getDelegate() {
@@ -475,6 +487,9 @@ public abstract class ModuleEditor implements Place.Navigator, Disposable {
try {
return method.invoke(myDelegateModel, unwrapParams(params));
}
catch (InvocationTargetException e) {
throw e.getCause();
}
finally {
if (needUpdate) {
updateOrderEntriesInEditors();
@@ -510,6 +525,9 @@ public abstract class ModuleEditor implements Place.Navigator, Disposable {
}
return result;
}
catch (InvocationTargetException e) {
throw e.getCause();
}
finally {
if (needUpdate) {
updateOrderEntriesInEditors();
@@ -30,12 +30,17 @@ import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.projectRoots.ui.Util;
import com.intellij.openapi.roots.AnnotationOrderRootType;
import com.intellij.openapi.roots.JavadocOrderRootType;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.impl.libraries.LibraryEx;
import com.intellij.openapi.roots.impl.libraries.LibraryImpl;
import com.intellij.openapi.roots.impl.libraries.LibraryTableImplUtil;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar;
import com.intellij.openapi.roots.libraries.LibraryUtil;
import com.intellij.openapi.roots.ui.configuration.LibraryTableModifiableModelProvider;
import com.intellij.openapi.roots.ui.configuration.ModuleEditor;
import com.intellij.openapi.roots.ui.configuration.PathUIUtils;
import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable;
import com.intellij.openapi.roots.ui.configuration.projectRoot.BaseLibrariesConfigurable;
@@ -72,6 +77,8 @@ import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.*;
import java.util.List;
@@ -1057,7 +1064,14 @@ public class LibraryTableEditor implements Disposable, LibraryEditorListener {
final NullableComputable<Library.ModifiableModel> computable = new NullableComputable<Library.ModifiableModel>() {
public Library.ModifiableModel compute() {
if (myTreeBuilder == null) {
final Library.ModifiableModel model = library.getModifiableModel();
// The following lines were born in severe pain & suffering, please respect
final InvocationHandler invocationHandler = Proxy.isProxyClass(library.getClass())? Proxy.getInvocationHandler(library) : null;
final Library realLibrary = invocationHandler instanceof ModuleEditor.ProxyDelegateAccessor? (Library)((ModuleEditor.ProxyDelegateAccessor)invocationHandler)
.getDelegate() : library;
final Module module = realLibrary instanceof LibraryImpl && ((LibraryImpl)realLibrary).isDisposed()? ((LibraryImpl)realLibrary).getModule() : null;
if (module != null && module.isDisposed()) return null; // no way
final Library targetLibrary = module != null? LibraryUtil.findLibrary(module, realLibrary.getName()) : realLibrary;
final Library.ModifiableModel model = targetLibrary.getModifiableModel();
modelRef.set(model);
return model;
}
@@ -8,9 +8,12 @@ import com.intellij.openapi.roots.impl.libraries.LibraryImpl;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar;
import com.intellij.openapi.roots.ui.configuration.ModuleEditor;
import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Collections;
import java.util.List;
@@ -58,7 +61,10 @@ public class LibraryProjectStructureElement extends ProjectStructureElement {
@NotNull
private Library getSourceOrThis() {
final Library source = ((LibraryImpl)myLibrary).getSource();
final InvocationHandler invocationHandler = Proxy.isProxyClass(myLibrary.getClass()) ? Proxy.getInvocationHandler(myLibrary) : null;
final Library realLibrary = invocationHandler instanceof ModuleEditor.ProxyDelegateAccessor ?
(Library)((ModuleEditor.ProxyDelegateAccessor)invocationHandler).getDelegate() : myLibrary;
final Library source = realLibrary instanceof LibraryImpl? ((LibraryImpl)realLibrary).getSource() : null;
return source != null ? source : myLibrary;
}
@@ -98,12 +98,12 @@ public class IdentifierHighlighterPass extends TextEditorHighlightingPass {
final PsiElement finalMyTarget = myTarget;
ReferencesSearch.search(myTarget, new LocalSearchScope(myFile)).forEach(new Processor<PsiReference>() {
public boolean process(final PsiReference psiReference) {
final TextRange textRange = HighlightUsagesHandler.getRangeToHighlight(psiReference);
final List<TextRange> textRanges = HighlightUsagesHandler.getRangesToHighlight(psiReference);
if (detector == null || detector.getReferenceAccess(finalMyTarget, psiReference) == ReadWriteAccessDetector.Access.Read) {
myReadAccessRanges.add(textRange);
myReadAccessRanges.addAll(textRanges);
}
else {
myWriteAccessRanges.add(textRange);
myWriteAccessRanges.addAll(textRanges);
}
return true;
}
@@ -365,19 +365,22 @@ public class HighlightUsagesHandler extends HighlightHandlerBase {
TextAttributes attributes, boolean clearHighlights) {
List<TextRange> textRanges = new ArrayList<TextRange>(refs.size());
for (PsiReference ref : refs) {
TextRange range = getRangeToHighlight(ref);
textRanges.add(range);
textRanges.addAll(getRangesToHighlight(ref));
}
highlightRanges(highlightManager, editor, attributes, clearHighlights, textRanges);
}
public static TextRange getRangeToHighlight(final PsiReference ref) {
PsiElement element = ref.getElement();
TextRange rangeInElement = ref.getRangeInElement();
TextRange range = element.getTextRange().cutOut(rangeInElement);
// injection occurs
range = InjectedLanguageManager.getInstance(element.getProject()).injectedToHost(element, range);
return range;
public static List<TextRange> getRangesToHighlight(final PsiReference ref) {
final List<TextRange> relativeRanges = ReferenceRange.getRanges(ref);
List<TextRange> answer = new ArrayList<TextRange>(relativeRanges.size());
for (TextRange relativeRange : relativeRanges) {
PsiElement element = ref.getElement();
TextRange range = element.getTextRange().cutOut(relativeRange);
// injection occurs
answer.add(InjectedLanguageManager.getInstance(element.getProject()).injectedToHost(element, range));
}
return answer;
}
@Nullable
@@ -37,7 +37,6 @@ import com.intellij.execution.ui.ConsoleView;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Key;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Roman Chernyatchik
@@ -57,25 +56,34 @@ public class SMTestRunnerConnectionUtil {
* just override "execute" method of your custom command line state and return
* test runner's console.
*
* NB: For debug purposes please enable "debug mode". In this mode test runner will also validate
* consistency of test events communication protocol and throw assertion errors. To enable debug mode
* please set system property idea.smrunner.debug=true
*
* @param processHandler Process handler
* @param consoleProperties Console properties for test console actions
* @param testFrameworkName Is used to store(project level) latest value of testTree/consoleTab splitter and other settings
* and also will be mentioned in debug diagnostics
* @return Console view
* @throws ExecutionException If IDEA cannot execute process this Exception will
* be catched and shown in error message box
* be caught and shown in error message box
*/
public static BaseTestsOutputConsoleView attachRunner(@NotNull final ProcessHandler processHandler,
@NotNull final TestConsoleProperties consoleProperties,
final RunnerSettings runnerSettings,
final ConfigurationPerRunnerSettings configurationSettings,
final String splitterPropertyName) throws ExecutionException {
@NotNull final String testFrameworkName) throws ExecutionException {
// Console
final String splitterPropertyName = testFrameworkName + ".Splitter.Proportion";
final SMTRunnerConsoleView testRunnerConsole = new SMTRunnerConsoleView(consoleProperties, runnerSettings, configurationSettings, splitterPropertyName);
testRunnerConsole.initUI();
final SMTestRunnerResultsForm resultsViewer = testRunnerConsole.getResultsViewer();
// attach listeners
attachEventsProcessors(consoleProperties, resultsViewer, resultsViewer.getStatisticsPane(), processHandler);
attachEventsProcessors(consoleProperties, resultsViewer,
resultsViewer.getStatisticsPane(),
processHandler, testFrameworkName);
testRunnerConsole.attachToProcess(processHandler);
return testRunnerConsole;
@@ -113,22 +121,29 @@ public class SMTestRunnerConnectionUtil {
* }
* </code>
*
*
* NB: For debug purposes please enable "debug mode". In this mode test runner will also validate
* consistency of test events communication protocol and throw assertion errors. To enable debug mode
* please set system property idea.smrunner.debug=true
*
* @param processHandler Process handler
* @param commandLineState Command line state
* @param config User run configuration settings
* @param splitterPropertyName This property will be used for storing splitter position.
* @param testFrameworkName Is used to store(project level) latest value of testTree/consoleTab splitter and other settings
* @return Console view
* @throws ExecutionException If IDEA cannot execute process this Exception will
* be catched and shown in error message box
* be caught and shown in error message box
*/
public static ConsoleView attachRunner(@NotNull final ProcessHandler processHandler,
@NotNull final CommandLineState commandLineState,
@NotNull final RuntimeConfiguration config,
@Nullable final String splitterPropertyName) throws ExecutionException {
final TestConsoleProperties consoleProperties = new SMTRunnerConsoleProperties(config);
@NotNull final String testFrameworkName) throws ExecutionException {
// final String testFrameworkName
final TestConsoleProperties consoleProperties = new SMTRunnerConsoleProperties(config, testFrameworkName);
return attachRunner(processHandler, consoleProperties,
commandLineState.getRunnerSettings(), commandLineState.getConfigurationSettings(), splitterPropertyName);
commandLineState.getRunnerSettings(),
commandLineState.getConfigurationSettings(), testFrameworkName);
}
/**
@@ -144,14 +159,16 @@ public class SMTestRunnerConnectionUtil {
private static ProcessHandler attachEventsProcessors(@NotNull final TestConsoleProperties consoleProperties,
final SMTestRunnerResultsForm resultsViewer,
final StatisticsPanel statisticsPane,
final ProcessHandler processHandler)
final ProcessHandler processHandler,
@NotNull final String testFrameworkName)
throws ExecutionException {
//build messages consumer
final OutputToGeneralTestEventsConverter outputConsumer = new OutputToGeneralTestEventsConverter();
final OutputToGeneralTestEventsConverter outputConsumer = new OutputToGeneralTestEventsConverter(testFrameworkName);
//events processor
final GeneralToSMTRunnerEventsConvertor eventsProcessor = new GeneralToSMTRunnerEventsConvertor(resultsViewer.getTestsRootNode());
final GeneralToSMTRunnerEventsConvertor eventsProcessor = new GeneralToSMTRunnerEventsConvertor(resultsViewer.getTestsRootNode(),
testFrameworkName);
// ui actions
final SMTRunnerUIActionsHandler uiActionsHandler = new SMTRunnerUIActionsHandler(consoleProperties);
@@ -31,18 +31,35 @@ import org.jetbrains.annotations.Nullable;
public interface GeneralTestEventsProcessor extends Disposable {
void onTestsCountInSuite(final int count);
void onTestStarted(final String testName, @Nullable final String locationUrl);
void onTestFinished(final String testName, final int duration);
void onTestFailure(final String testName, final String localizedMessage, final String stackTrace,
void onTestStarted(@NotNull final String testName,
@Nullable final String locationUrl);
void onTestFinished(@NotNull final String testName,
final int duration);
void onTestFailure(@NotNull final String testName,
@NotNull final String localizedMessage,
@Nullable final String stackTrace,
final boolean testError);
void onTestIgnored(final String testName, final String ignoreComment, @Nullable final String stackTrace);
void onTestOutput(final String testName, final String text, final boolean stdOut);
void onSuiteStarted(final String suiteName, @Nullable final String locationUrl);
void onSuiteFinished(final String suiteName);
void onTestIgnored(@NotNull final String testName,
@NotNull final String ignoreComment,
@Nullable final String stackTrace);
void onUncapturedOutput(final String text, final Key outputType);
void onError(@NotNull final String localizedMessage, @Nullable final String stackTrace);
void onTestOutput(@NotNull final String testName,
@NotNull final String text,
final boolean stdOut);
void onSuiteStarted(@NotNull final String suiteName,
@Nullable final String locationUrl);
void onSuiteFinished(@NotNull final String suiteName);
void onUncapturedOutput(@NotNull final String text,
final Key outputType);
void onError(@NotNull final String localizedMessage,
@Nullable final String stackTrace);
// Custom progress statistics
@@ -51,7 +68,8 @@ public interface GeneralTestEventsProcessor extends Disposable {
* If name is null statistics will be switched to normal mode
* @param testCount - 0 will be considered as unknown tests number
*/
void onCustomProgressTestsCategory(@Nullable final String categoryName, final int testCount);
void onCustomProgressTestsCategory(@Nullable final String categoryName,
final int testCount);
void onCustomProgressTestStarted();
void onCustomProgressTestFailed();
}
@@ -18,6 +18,7 @@ package com.intellij.execution.testframework.sm.runner;
import com.intellij.execution.process.ProcessOutputTypes;
import com.intellij.execution.testframework.AbstractTestProxy;
import com.intellij.execution.testframework.sm.SMRunnerUtil;
import com.intellij.execution.testframework.sm.SMTestRunnerConnectionUtil;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
@@ -43,10 +44,13 @@ public class GeneralToSMTRunnerEventsConvertor implements GeneralTestEventsProce
private final TestSuiteStack mySuitesStack = new TestSuiteStack();
private final List<SMTRunnerEventsListener> myEventsListeners = new ArrayList<SMTRunnerEventsListener>();
private final SMTestProxy myTestsRootNode;
private final String myTestFrameworkName;
private boolean myIsTestingFinished;
public GeneralToSMTRunnerEventsConvertor(@NotNull final SMTestProxy testsRootNode) {
public GeneralToSMTRunnerEventsConvertor(@NotNull final SMTestProxy testsRootNode,
@NotNull final String testFrameworkName) {
myTestsRootNode = testsRootNode;
myTestFrameworkName = testFrameworkName;
}
public void addEventsListener(final SMTRunnerEventsListener listener) {
@@ -92,15 +96,21 @@ public class GeneralToSMTRunnerEventsConvertor implements GeneralTestEventsProce
});
}
public void onTestStarted(final String testName, final String locationUrl) {
public void onTestStarted(@NotNull final String testName,
@Nullable final String locationUrl) {
SMRunnerUtil.addToInvokeLater(new Runnable() {
public void run() {
final String fullName = getFullTestName(testName);
if (myRunningTestsFullNameToProxy.containsKey(fullName)) {
//Dublicated event
LOG.warn("Test [" + fullName + "] has been already started");
return;
//Duplicated event
final boolean inDebugMode = SMTestRunnerConnectionUtil.isInDebugMode();
logProblem("Test [" + fullName + "] has been already started",
inDebugMode);
if (inDebugMode) {
return;
}
}
final SMTestProxy parentSuite = getCurrentSuite();
@@ -120,7 +130,7 @@ public class GeneralToSMTRunnerEventsConvertor implements GeneralTestEventsProce
});
}
public void onSuiteStarted(final String suiteName, @Nullable final String locationUrl) {
public void onSuiteStarted(@NotNull final String suiteName, @Nullable final String locationUrl) {
SMRunnerUtil.addToInvokeLater(new Runnable() {
public void run() {
final SMTestProxy parentSuite = getCurrentSuite();
@@ -139,14 +149,16 @@ public class GeneralToSMTRunnerEventsConvertor implements GeneralTestEventsProce
});
}
public void onTestFinished(final String testName, final int duration) {
public void onTestFinished(@NotNull final String testName,
@Nullable final int duration) {
SMRunnerUtil.addToInvokeLater(new Runnable() {
public void run() {
final String fullTestName = getFullTestName(testName);
final SMTestProxy testProxy = getProxyByFullTestName(fullTestName);
if (testProxy == null) {
LOG.warn("Test wasn't started! TestFinished event: name = {" + testName + "}. " +
cannotFindFullTestNameMsg(fullTestName));
logProblem("Test wasn't started! TestFinished event: name = {" + testName + "}. " +
cannotFindFullTestNameMsg(fullTestName));
return;
}
@@ -160,7 +172,7 @@ public class GeneralToSMTRunnerEventsConvertor implements GeneralTestEventsProce
});
}
public void onSuiteFinished(final String suiteName) {
public void onSuiteFinished(@NotNull final String suiteName) {
SMRunnerUtil.addToInvokeLater(new Runnable() {
public void run() {
final SMTestProxy mySuite = mySuitesStack.popSuite(suiteName);
@@ -174,7 +186,7 @@ public class GeneralToSMTRunnerEventsConvertor implements GeneralTestEventsProce
});
}
public void onUncapturedOutput(final String text, final Key outputType) {
public void onUncapturedOutput(@NotNull final String text, final Key outputType) {
SMRunnerUtil.addToInvokeLater(new Runnable() {
public void run() {
final SMTestProxy currentProxy = findCurrentTestOrSuite();
@@ -225,27 +237,50 @@ public class GeneralToSMTRunnerEventsConvertor implements GeneralTestEventsProce
});
}
public void onTestFailure(final String testName,
final String localizedMessage, final String stackTrace,
public void onTestFailure(@NotNull final String testName,
@NotNull final String localizedMessage,
@Nullable final String stackTrace,
final boolean isTestError) {
SMRunnerUtil.addToInvokeLater(new Runnable() {
public void run() {
final boolean inDebugMode = SMTestRunnerConnectionUtil.isInDebugMode();
final String fullTestName = getFullTestName(testName);
final SMTestProxy testProxy = getProxyByFullTestName(fullTestName);
SMTestProxy testProxy = getProxyByFullTestName(fullTestName);
if (testProxy == null) {
LOG.warn("Test wasn't started! TestFailure event: name = {" + testName + "}" +
", message = {" + localizedMessage + "}" +
", stackTrace = {" + stackTrace + "}. " +
cannotFindFullTestNameMsg(fullTestName));
return;
}
// if wasn't processed
if (myFailedTestsSet.contains(testProxy)) {
// dublicate message
LOG.warn("Duplicate failure for test [" + fullTestName + "]: msg = " + localizedMessage + ", stacktrace = " + stackTrace);
return;
logProblem("Test wasn't started! TestFailure event: name = {" + testName + "}" +
", message = {" + localizedMessage + "}" +
", stackTrace = {" + stackTrace + "}. " +
cannotFindFullTestNameMsg(fullTestName),
inDebugMode);
if (inDebugMode) {
return;
} else {
// try to fix the problem:
if (!myFailedTestsSet.contains(testProxy)) {
// if hasn't been already reported
// 1. report
onTestStarted(testName, null);
// 2. add failure
testProxy = getProxyByFullTestName(fullTestName);
}
}
}
// check if has been already processed
if (myFailedTestsSet.contains(testProxy)) {
// duplicate message
logProblem("Duplicate failure for test [" + fullTestName + "]: msg = " + localizedMessage + ", stacktrace = " + stackTrace,
inDebugMode);
if (inDebugMode) {
return;
}
}
if (testProxy == null) {
return;
}
testProxy.setTestFailed(localizedMessage, stackTrace, isTestError);
@@ -257,20 +292,35 @@ public class GeneralToSMTRunnerEventsConvertor implements GeneralTestEventsProce
});
}
public void onTestIgnored(final String testName, final String ignoreComment,
public void onTestIgnored(@NotNull final String testName,
@NotNull final String ignoreComment,
@Nullable final String stackTrace) {
SMRunnerUtil.addToInvokeLater(new Runnable() {
public void run() {
final String fullTestName = getFullTestName(testName);
final SMTestProxy testProxy = getProxyByFullTestName(fullTestName);
SMTestProxy testProxy = getProxyByFullTestName(fullTestName);
if (testProxy == null) {
final boolean debugMode = SMTestRunnerConnectionUtil.isInDebugMode();
logProblem("Test wasn't started! " +
"TestIgnored event: name = {" + testName + "}, " +
"message = {" + ignoreComment + "}. " +
cannotFindFullTestNameMsg(fullTestName),
debugMode);
if (debugMode) {
return;
} else {
// try to fix
// 1. report test opened
onTestStarted(testName, null);
// 2. report failure
testProxy = getProxyByFullTestName(fullTestName);
}
}
if (testProxy == null) {
LOG.warn("Test wasn't started! " +
"TestIgnored event: name = {" + testName + "}, " +
"message = {" + ignoreComment + "}. " +
cannotFindFullTestNameMsg(fullTestName));
return;
}
testProxy.setTestIgnored(ignoreComment, stackTrace);
// fire event
@@ -279,17 +329,17 @@ public class GeneralToSMTRunnerEventsConvertor implements GeneralTestEventsProce
});
}
public void onTestOutput(final String testName,
final String text, final boolean stdOut) {
public void onTestOutput(@NotNull final String testName,
@NotNull final String text, final boolean stdOut) {
SMRunnerUtil.addToInvokeLater(new Runnable() {
public void run() {
final String fullTestName = getFullTestName(testName);
final SMTestProxy testProxy = getProxyByFullTestName(fullTestName);
if (testProxy == null) {
LOG.warn("Test wasn't started! TestOutput event: name = {" + testName + "}, " +
"isStdOut = " + stdOut + ", " +
"text = {" + text + "}. " +
cannotFindFullTestNameMsg(fullTestName));
logProblem("Test wasn't started! TestOutput event: name = {" + testName + "}, " +
"isStdOut = " + stdOut + ", " +
"text = {" + text + "}. " +
cannotFindFullTestNameMsg(fullTestName));
return;
}
@@ -320,7 +370,7 @@ public class GeneralToSMTRunnerEventsConvertor implements GeneralTestEventsProce
// current suite shouldn't be null otherwise test runner isn't correct
// or may be we are in debug mode
LOG.warn("Current suite is undefined. Root suite will be used.");
logProblem("Current suite is undefined. Root suite will be used.");
return myTestsRootNode;
}
@@ -449,7 +499,7 @@ public class GeneralToSMTRunnerEventsConvertor implements GeneralTestEventsProce
if (!myRunningTestsFullNameToProxy.isEmpty()) {
final Application application = ApplicationManager.getApplication();
if (!application.isHeadlessEnvironment() && !application.isUnitTestMode()) {
LOG.warn("Not all events were processed! " + dumpRunningTestsNames());
logProblem("Not all events were processed! " + dumpRunningTestsNames());
}
}
myRunningTestsFullNameToProxy.clear();
@@ -473,4 +523,21 @@ public class GeneralToSMTRunnerEventsConvertor implements GeneralTestEventsProce
}
return currentProxy;
}
public static String getTFrameworkPrefix(final String testFrameworkName) {
return "[" + testFrameworkName + "]: ";
}
private void logProblem(final String msg) {
logProblem(msg, SMTestRunnerConnectionUtil.isInDebugMode());
}
private void logProblem(final String msg, boolean throwError) {
final String text = getTFrameworkPrefix(myTestFrameworkName) + msg;
if (throwError) {
LOG.error(text);
}
else {
LOG.warn(text);
}
}
}
@@ -29,6 +29,8 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static com.intellij.execution.testframework.sm.runner.GeneralToSMTRunnerEventsConvertor.getTFrameworkPrefix;
/**
* @author Roman Chernyatchik
*
@@ -42,6 +44,7 @@ public class OutputToGeneralTestEventsConverter implements ProcessOutputConsumer
private GeneralTestEventsProcessor myProcessor;
private final MyServiceMessageVisitor myServiceMessageVisitor;
private final String myTestFrameworkName;
private static class OutputChunk {
private final Key myKey;
@@ -67,7 +70,8 @@ public class OutputToGeneralTestEventsConverter implements ProcessOutputConsumer
private final List<OutputChunk> myOutputChunks;
public OutputToGeneralTestEventsConverter() {
public OutputToGeneralTestEventsConverter(@NotNull final String testFrameworkName) {
myTestFrameworkName = testFrameworkName;
myServiceMessageVisitor = new MyServiceMessageVisitor();
myOutputChunks = new ArrayList<OutputChunk>();
}
@@ -165,11 +169,14 @@ public class OutputToGeneralTestEventsConverter implements ProcessOutputConsumer
}
}
catch (ParseException e) {
LOG.error(e);
LOG.error(getTFrameworkPrefix(myTestFrameworkName) + "Parsing error.", e);
}
}
private void fireOnTestStarted(final String testName, @Nullable final String locationUrl) {
assertNotNull(testName);
// local variable is used to prevent concurrent modification
final GeneralTestEventsProcessor processor = myProcessor;
if (processor != null) {
@@ -179,6 +186,8 @@ public class OutputToGeneralTestEventsConverter implements ProcessOutputConsumer
private void fireOnTestFailure(final String testName, final String localizedMessage, final String stackTrace,
final boolean isTestError) {
assertNotNull(testName);
assertNotNull(localizedMessage);
// local variable is used to prevent concurrent modification
final GeneralTestEventsProcessor processor = myProcessor;
@@ -189,6 +198,8 @@ public class OutputToGeneralTestEventsConverter implements ProcessOutputConsumer
private void fireOnTestIgnored(final String testName, final String ignoreComment,
@Nullable final String details) {
assertNotNull(testName);
assertNotNull(ignoreComment);
// local variable is used to prevent concurrent modification
final GeneralTestEventsProcessor processor = myProcessor;
@@ -198,6 +209,8 @@ public class OutputToGeneralTestEventsConverter implements ProcessOutputConsumer
}
private void fireOnTestFinished(final String testName, final int duration) {
assertNotNull(testName);
// local variable is used to prevent concurrent modification
final GeneralTestEventsProcessor processor = myProcessor;
if (processor != null) {
@@ -205,7 +218,10 @@ public class OutputToGeneralTestEventsConverter implements ProcessOutputConsumer
}
}
private void fireOnCustomProgressTestsCategory(@NotNull final String categoryName, int testsCount) {
private void fireOnCustomProgressTestsCategory(final String categoryName,
int testsCount) {
assertNotNull(categoryName);
final GeneralTestEventsProcessor processor = myProcessor;
if (processor != null) {
final boolean disableCustomMode = StringUtil.isEmpty(categoryName);
@@ -229,6 +245,9 @@ public class OutputToGeneralTestEventsConverter implements ProcessOutputConsumer
}
private void fireOnTestOutput(final String testName, final String text, final boolean stdOut) {
assertNotNull(testName);
assertNotNull(text);
// local variable is used to prevent concurrent modification
final GeneralTestEventsProcessor processor = myProcessor;
if (processor != null) {
@@ -237,6 +256,8 @@ public class OutputToGeneralTestEventsConverter implements ProcessOutputConsumer
}
private void fireOnUncapturedOutput(final String text, final Key outputType) {
assertNotNull(text);
// local variable is used to prevent concurrent modification
final GeneralTestEventsProcessor processor = myProcessor;
if (processor != null) {
@@ -253,6 +274,8 @@ public class OutputToGeneralTestEventsConverter implements ProcessOutputConsumer
}
private void fireOnSuiteStarted(final String suiteName, @Nullable final String locationUrl) {
assertNotNull(suiteName);
// local variable is used to prevent concurrent modification
final GeneralTestEventsProcessor processor = myProcessor;
if (processor != null) {
@@ -261,6 +284,8 @@ public class OutputToGeneralTestEventsConverter implements ProcessOutputConsumer
}
private void fireOnSuiteFinished(final String suiteName) {
assertNotNull(suiteName);
// local variable is used to prevent concurrent modification
final GeneralTestEventsProcessor processor = myProcessor;
if (processor != null) {
@@ -268,8 +293,9 @@ public class OutputToGeneralTestEventsConverter implements ProcessOutputConsumer
}
}
private void fireOnErrorMsg(@NotNull final String localizedMessage,
private void fireOnErrorMsg(final String localizedMessage,
@Nullable final String stackTrace) {
assertNotNull(localizedMessage);
// local variable is used to prevent concurrent modification
final GeneralTestEventsProcessor processor = myProcessor;
@@ -278,6 +304,12 @@ public class OutputToGeneralTestEventsConverter implements ProcessOutputConsumer
}
}
private void assertNotNull(final String s) {
if (s == null) {
LOG.error(getTFrameworkPrefix(myTestFrameworkName) + " @NotNull value is expected.");
}
}
private class MyServiceMessageVisitor extends DefaultServiceMessageVisitor {
@NonNls public static final String KEY_TESTS_COUNT = "testCount";
@NonNls private static final String ATTR_KEY_TEST_ERROR = "error";
@@ -306,14 +338,15 @@ public class OutputToGeneralTestEventsConverter implements ProcessOutputConsumer
}
@Nullable
private String fetchTestLocation(TestSuiteStarted suiteStarted) {
private String fetchTestLocation(final TestSuiteStarted suiteStarted) {
final Map<String, String> attrs = suiteStarted.getAttributes();
final String location = attrs.get(ATTR_KEY_LOCATION_URL);
if (location == null) {
// try old API
final String oldLocation = attrs.get(ATTR_KEY_LOCATION_URL_OLD);
if (oldLocation != null) {
LOG.error("Test Runner API was changed for TeamCity 5.0 compatibility. Please use 'locationHint' attribute instead of 'location'.");
LOG.error(getTFrameworkPrefix(myTestFrameworkName)
+ "Test Runner API was changed for TeamCity 5.0 compatibility. Please use 'locationHint' attribute instead of 'location'.");
return oldLocation;
}
return null;
@@ -441,7 +474,7 @@ public class OutputToGeneralTestEventsConverter implements ProcessOutputConsumer
try {
count = Integer.parseInt(countStr);
} catch (NumberFormatException ex) {
LOG.error(ex);
LOG.error(getTFrameworkPrefix(myTestFrameworkName) + "Parse integer error.", ex);
}
return count;
}
@@ -21,19 +21,22 @@ import com.intellij.ide.util.PropertiesComponent;
import com.intellij.util.config.Storage;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.XDebuggerManager;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
/**
* @author: Roman Chernyatchik
*/
public class SMTRunnerConsoleProperties extends TestConsoleProperties {
@NonNls private static final String PREFIX = "RubyTestUnitSupport.";
private final RuntimeConfiguration myConfiguration;
public SMTRunnerConsoleProperties(final RuntimeConfiguration config)
/**
* @param config
* @param testFrameworkName Prefix for storage which keeps runner settings. E.g. "RubyTestUnit"
*/
public SMTRunnerConsoleProperties(final RuntimeConfiguration config,
final String testFrameworkName)
{
super(new Storage.PropertiesComponentStorage(PREFIX, PropertiesComponent.getInstance()), config.getProject());
super(new Storage.PropertiesComponentStorage(testFrameworkName + "Support.", PropertiesComponent.getInstance()), config.getProject());
myConfiguration = config;
}
@@ -282,7 +282,8 @@ public class SMTestProxy extends CompositePrintable implements PrintableTestProx
}
public void setTestFailed(@NotNull final String localizedMessage,
@NotNull final String stackTrace, final boolean testError) {
@Nullable final String stackTrace,
final boolean testError) {
myState = testError
? new TestErrorState(localizedMessage, stackTrace)
: new TestFailedState(localizedMessage, stackTrace);
@@ -15,11 +15,14 @@
*/
package com.intellij.execution.testframework.sm.runner.states;
import org.jetbrains.annotations.Nullable;
/**
* @author Roman Chernyatchik
*/
public class TestErrorState extends TestFailedState {
public TestErrorState(final String localizedMessage, final String stackTrace) {
public TestErrorState(@Nullable final String localizedMessage,
@Nullable final String stackTrace) {
super(localizedMessage, stackTrace);
}
@@ -43,6 +43,13 @@ public class SMTRunnerConsoleView extends BaseTestsOutputConsoleView {
this(consoleProperties, runnerSettings, configurationPerRunnerSettings, null);
}
/**
*
* @param consoleProperties
* @param runnerSettings
* @param configurationPerRunnerSettings
* @param splitterProperty Key to store(project level) latest value of testTree/consoleTab splitter. E.g. "RSpec.Splitter.Proportion"
*/
public SMTRunnerConsoleView(final TestConsoleProperties consoleProperties, final RunnerSettings runnerSettings,
final ConfigurationPerRunnerSettings configurationPerRunnerSettings,
@Nullable final String splitterProperty) {
@@ -81,7 +81,7 @@ public abstract class BaseSMTRunnerTestCase extends LightPlatformTestCase {
protected TestConsoleProperties createConsoleProperties() {
final RuntimeConfiguration runConfiguration = createRunConfiguration();
final TestConsoleProperties consoleProperties = new SMTRunnerConsoleProperties(runConfiguration);
final TestConsoleProperties consoleProperties = new SMTRunnerConsoleProperties(runConfiguration, "SMRunnerTests");
TestConsoleProperties.HIDE_PASSED_TESTS.set(consoleProperties, false);
return consoleProperties;
@@ -53,7 +53,7 @@ public class GeneralToSMTRunnerEventsConvertorTest extends BaseSMTRunnerTestCase
myConsole = new SMTRunnerConsoleView(consoleProperties, environment.getRunnerSettings(), environment.getConfigurationSettings());
myConsole.initUI();
myResultsViewer = myConsole.getResultsViewer();
myEventsProcessor = new GeneralToSMTRunnerEventsConvertor(myResultsViewer.getTestsRootNode());
myEventsProcessor = new GeneralToSMTRunnerEventsConvertor(myResultsViewer.getTestsRootNode(), "SMTestFramework");
myEventsProcessor.addEventsListener(myResultsViewer);
myTreeModel = myResultsViewer.getTreeView().getModel();
@@ -72,7 +72,7 @@ public class SMTRunnerConsoleTest extends BaseSMTRunnerTestCase {
myConsole.initUI();
myResultsViewer = myConsole.getResultsViewer();
myRootSuite = myResultsViewer.getTestsRootNode();
myEventsProcessor = new GeneralToSMTRunnerEventsConvertor(myResultsViewer.getTestsRootNode());
myEventsProcessor = new GeneralToSMTRunnerEventsConvertor(myResultsViewer.getTestsRootNode(), "SMTestFramework");
myEventsProcessor.onStartTesting();
}
@@ -59,7 +59,7 @@ public class SMTestRunnerResultsFormTest extends BaseSMTRunnerTestCase {
myConsole.initUI();
myResultsViewer = myConsole.getResultsViewer();
myTestsRootNode = myResultsViewer.getTestsRootNode();
myEventsProcessor = new GeneralToSMTRunnerEventsConvertor(myResultsViewer.getTestsRootNode());
myEventsProcessor = new GeneralToSMTRunnerEventsConvertor(myResultsViewer.getTestsRootNode(), "SMTestFramework");
myEventsProcessor.addEventsListener(myResultsViewer);
myTreeModel = myResultsViewer.getTreeView().getModel();
}
@@ -638,7 +638,7 @@ public class TestsPresentationUtilTest extends BaseSMTRunnerTestCase {
public MyRenderer(final boolean isPaused,
final UITestUtil.FragmentsContainer fragmentsContainer) {
super(new SMTRunnerConsoleProperties(createRunConfiguration()) {
super(new SMTRunnerConsoleProperties(createRunConfiguration(), "SMRunnerTests") {
@Override
public boolean isPaused() {
return isPaused;