diff --git a/java/execution/impl/src/com/intellij/execution/JavaTestFrameworkRunnableState.java b/java/execution/impl/src/com/intellij/execution/JavaTestFrameworkRunnableState.java index 3bfc53a282bc..edec7cf891be 100644 --- a/java/execution/impl/src/com/intellij/execution/JavaTestFrameworkRunnableState.java +++ b/java/execution/impl/src/com/intellij/execution/JavaTestFrameworkRunnableState.java @@ -19,6 +19,7 @@ import com.intellij.ExtensionPoints; import com.intellij.debugger.impl.GenericDebuggerRunnerSettings; import com.intellij.diagnostic.logging.OutputFileUtil; import com.intellij.execution.configurations.*; +import com.intellij.execution.impl.ConsoleBuffer; import com.intellij.execution.process.OSProcessHandler; import com.intellij.execution.process.ProcessAdapter; import com.intellij.execution.process.ProcessEvent; @@ -125,14 +126,6 @@ public abstract class JavaTestFrameworkRunnableState -1 ? trace.substring(failureIdx + failureMessageLength) : trace); + String details = failureIdx > -1 ? trace.substring(failureIdx + failureMessageLength) : trace; + attrs.put("details", details); if (notification != null) { final int expectedIdx = trace.indexOf(expectedPrefix); @@ -101,18 +105,26 @@ public class ComparisonFailureData { attrs.put("message", comparisonFailureMessage); final String filePath = notification.getFilePath(); + final String actualFilePath = notification.getActualFilePath(); + final String expected = notification.getExpected(); + final String actual = notification.getActual(); + + int fullLength = (filePath == null && expected != null ? expected.length() : 0) + + (actualFilePath == null && actual != null ? actual.length() : 0) + + details.length() + + comparisonFailureMessage.length() + 100; if (filePath != null) { attrs.put("expectedFile", filePath); } else { - attrs.put("expected", notification.getExpected()); + writeDiffSide(attrs, "expected", expected, fullLength); } - final String actualFilePath = notification.getActualFilePath(); + if (actualFilePath != null) { attrs.put("actualFile", actualFilePath); } else { - attrs.put("actual", notification.getActual()); + writeDiffSide(attrs, "actual", actual, fullLength); } } else { @@ -130,6 +142,37 @@ public class ComparisonFailureData { } } + private static void writeDiffSide(Map attrs, final String expectedOrActualPrefix, final String text, int fullLength) { + String property = System.getProperty("idea.test.cyclic.buffer.size"); + + int threshold; + try { + threshold = Integer.parseInt(property); + } + catch (NumberFormatException ignored) { + threshold = -1; + } + + if (threshold > 0 && fullLength > threshold) { + try { + //noinspection SSBasedInspection + File tempFile = File.createTempFile(expectedOrActualPrefix, ""); + OutputStream stream = new FileOutputStream(tempFile, false); + try { + stream.write(text.getBytes("UTF-8"), 0, text.length()); + } + finally { + stream.close(); + } + attrs.put(expectedOrActualPrefix + "File", tempFile.getAbsolutePath()); + attrs.put(expectedOrActualPrefix + "IsTempFile", "true"); + return; + } + catch (Throwable ignored) {} + } + attrs.put(expectedOrActualPrefix, text); + } + public static boolean isAssertionError(Class throwableClass) { if (throwableClass == null) return false; final String throwableClassName = throwableClass.getName(); diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralIdBasedToSMTRunnerEventsConvertor.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralIdBasedToSMTRunnerEventsConvertor.java index f599c5f9f8a7..e18b6e875ca3 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralIdBasedToSMTRunnerEventsConvertor.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralIdBasedToSMTRunnerEventsConvertor.java @@ -254,10 +254,7 @@ public class GeneralIdBasedToSMTRunnerEventsConvertor extends GeneralTestEventsP String failureMessage = testFailedEvent.getLocalizedFailureMessage(); String stackTrace = testFailedEvent.getStacktrace(); if (comparisonFailureActualText != null && comparisonFailureExpectedText != null) { - testProxy.setTestComparisonFailed(failureMessage, stackTrace, - comparisonFailureActualText, comparisonFailureExpectedText, - testFailedEvent.getExpectedFilePath(), - testFailedEvent.getActualFilePath()); + testProxy.setTestComparisonFailed(failureMessage, stackTrace, comparisonFailureActualText, comparisonFailureExpectedText, testFailedEvent); } else if (comparisonFailureActualText == null && comparisonFailureExpectedText == null) { testProxy.setTestFailed(failureMessage, stackTrace, testFailedEvent.isTestError()); } else { diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertor.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertor.java index bae16c1d0081..6616a416550b 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertor.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertor.java @@ -386,9 +386,7 @@ public class GeneralToSMTRunnerEventsConvertor extends GeneralTestEventsProcesso } if (comparisionFailureActualText != null && comparisionFailureExpectedText != null) { - testProxy.setTestComparisonFailed(localizedMessage, stackTrace, - comparisionFailureActualText, comparisionFailureExpectedText, - testFailedEvent.getExpectedFilePath(), testFailedEvent.getActualFilePath()); + testProxy.setTestComparisonFailed(localizedMessage, stackTrace, comparisionFailureActualText, comparisionFailureExpectedText, testFailedEvent); } else if (comparisionFailureActualText == null && comparisionFailureExpectedText == null) { testProxy.setTestFailed(localizedMessage, stackTrace, isTestError); diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java index bf4027c68465..dedaf587a646 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java @@ -20,6 +20,7 @@ import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.testframework.*; import com.intellij.execution.testframework.sm.SMStacktraceParser; import com.intellij.execution.testframework.sm.SMStacktraceParserEx; +import com.intellij.execution.testframework.sm.runner.events.TestFailedEvent; import com.intellij.execution.testframework.sm.runner.states.*; import com.intellij.execution.testframework.sm.runner.ui.TestsPresentationUtil; import com.intellij.execution.testframework.stacktrace.DiffHyperlink; @@ -29,6 +30,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; @@ -446,23 +448,26 @@ public class SMTestProxy extends AbstractTestProxy { @Nullable final String stackTrace, @NotNull final String actualText, @NotNull final String expectedText) { - setTestComparisonFailed(localizedMessage, stackTrace, actualText, expectedText, null); + setTestComparisonFailed(localizedMessage, stackTrace, actualText, expectedText, null, null); } public void setTestComparisonFailed(@NotNull final String localizedMessage, @Nullable final String stackTrace, @NotNull final String actualText, @NotNull final String expectedText, - @Nullable final String filePath) { - setTestComparisonFailed(localizedMessage, stackTrace, actualText, expectedText, filePath, null); + @NotNull final TestFailedEvent event) { + TestComparisionFailedState comparisionFailedState = + setTestComparisonFailed(localizedMessage, stackTrace, actualText, expectedText, event.getExpectedFilePath(), event.getActualFilePath()); + comparisionFailedState.setToDeleteExpectedFile(event.isExpectedFIleTemp()); + comparisionFailedState.setToDeleteActualFile(event.isActualFileTemp()); } - public void setTestComparisonFailed(@NotNull final String localizedMessage, - @Nullable final String stackTrace, - @NotNull final String actualText, - @NotNull final String expectedText, - @Nullable final String expectedFilePath, - @Nullable final String actualFilePath) { + public TestComparisionFailedState setTestComparisonFailed(@NotNull final String localizedMessage, + @Nullable final String stackTrace, + @NotNull final String actualText, + @NotNull final String expectedText, + @Nullable final String expectedFilePath, + @Nullable final String actualFilePath) { setStacktraceIfNotSet(stackTrace); final TestComparisionFailedState comparisionFailedState = new TestComparisionFailedState(localizedMessage, stackTrace, actualText, expectedText, expectedFilePath, actualFilePath); if (myState instanceof CompoundTestFailedState) { @@ -478,6 +483,16 @@ public class SMTestProxy extends AbstractTestProxy { myState = comparisionFailedState; } fireOnNewPrintable(comparisionFailedState); + return comparisionFailedState; + } + + @Override + public void dispose() { + if (myState instanceof TestFailedState) { + Disposer.dispose((TestFailedState)myState); + } + + super.dispose(); } public void setTestIgnored(@Nullable String ignoreComment, @Nullable String stackTrace) { diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/events/TestFailedEvent.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/events/TestFailedEvent.java index 0b3932f2bb84..d629b14e6214 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/events/TestFailedEvent.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/events/TestFailedEvent.java @@ -23,6 +23,7 @@ import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.IOException; +import java.util.Map; public class TestFailedEvent extends TreeNodeEvent { @@ -34,6 +35,8 @@ public class TestFailedEvent extends TreeNodeEvent { private final String myExpectedFilePath; private final String myActualFilePath; private final long myDurationMillis; + private boolean myExpectedFileTemp; + private boolean myActualFileTemp; public TestFailedEvent(@NotNull TestFailed testFailed, boolean testError) { this(testFailed, testError, null); @@ -71,7 +74,18 @@ public class TestFailedEvent extends TreeNodeEvent { } myComparisonFailureActualText = actual; - myDurationMillis = parseDuration(testFailed.getAttributes().get("duration")); + Map attributes = testFailed.getAttributes(); + myDurationMillis = parseDuration(attributes.get("duration")); + myActualFileTemp = Boolean.parseBoolean(attributes.get("actualIsTempFile")); + myExpectedFileTemp = Boolean.parseBoolean(attributes.get("expectedIsTempFile")); + } + + public boolean isExpectedFIleTemp() { + return myExpectedFileTemp; + } + + public boolean isActualFileTemp() { + return myActualFileTemp; } private static long parseDuration(@Nullable String durationStr) { @@ -99,6 +113,9 @@ public class TestFailedEvent extends TreeNodeEvent { comparisonFailureActualText, comparisonFailureExpectedText, null, + null, + false, + false, -1); } @@ -110,6 +127,9 @@ public class TestFailedEvent extends TreeNodeEvent { @Nullable String comparisonFailureActualText, @Nullable String comparisonFailureExpectedText, @Nullable String expectedFilePath, + @Nullable String actualFilePath, + boolean expectedFileTemp, + boolean actualFileTemp, long durationMillis) { super(testName, id); myLocalizedFailureMessage = localizedFailureMessage; @@ -124,9 +144,11 @@ public class TestFailedEvent extends TreeNodeEvent { } myComparisonFailureActualText = comparisonFailureActualText; - myActualFilePath = null; + myActualFilePath = actualFilePath; myComparisonFailureExpectedText = comparisonFailureExpectedText; myDurationMillis = durationMillis; + myExpectedFileTemp = expectedFileTemp; + myActualFileTemp = actualFileTemp; } @NotNull diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/CompoundTestFailedState.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/CompoundTestFailedState.java index da7c58b8e603..1e4bfece8292 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/CompoundTestFailedState.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/CompoundTestFailedState.java @@ -18,7 +18,7 @@ package com.intellij.execution.testframework.sm.runner.states; import com.intellij.execution.testframework.Printer; import com.intellij.execution.testframework.stacktrace.DiffHyperlink; -import com.intellij.util.Function; +import com.intellij.openapi.util.Disposer; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -36,6 +36,7 @@ public class CompoundTestFailedState extends TestFailedState { public void addFailure(TestFailedState state) { myStates.add(state); + Disposer.register(this, state); } @Override diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/TestComparisionFailedState.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/TestComparisionFailedState.java index 7b30bf33436b..495ba4e4cbe2 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/TestComparisionFailedState.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/TestComparisionFailedState.java @@ -20,10 +20,13 @@ import com.intellij.execution.testframework.CompositePrintable; import com.intellij.execution.testframework.Printer; import com.intellij.execution.testframework.stacktrace.DiffHyperlink; import com.intellij.execution.ui.ConsoleViewContentType; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.File; + /** * @author Roman.Chernyatchik */ @@ -31,6 +34,8 @@ public class TestComparisionFailedState extends TestFailedState { private final String myErrorMsgPresentation; private final String myStacktracePresentation; private DiffHyperlink myHyperlink; + private boolean myToDeleteExpectedFile; + private boolean myToDeleteActualFile; public TestComparisionFailedState(@Nullable final String localizedMessage, @@ -82,4 +87,21 @@ public class TestComparisionFailedState extends TestFailedState { public DiffHyperlink getHyperlink() { return myHyperlink; } + + public void setToDeleteExpectedFile(boolean expectedTemp) { + myToDeleteExpectedFile = expectedTemp; + } + + public void setToDeleteActualFile(boolean actualTemp) { + myToDeleteActualFile = actualTemp; + } + + public void dispose() { + if (myToDeleteActualFile) { + FileUtil.delete(new File(myHyperlink.getActualFilePath())); + } + if (myToDeleteExpectedFile) { + FileUtil.delete(new File(myHyperlink.getFilePath())); + } + } } diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/TestFailedState.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/TestFailedState.java index a8ba9a6d884c..f013dfb11cc8 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/TestFailedState.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/TestFailedState.java @@ -19,6 +19,7 @@ import com.intellij.execution.process.ProcessOutputTypes; import com.intellij.execution.testframework.CompositePrintable; import com.intellij.execution.testframework.Printer; import com.intellij.execution.ui.ConsoleViewContentType; +import com.intellij.openapi.Disposable; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; @@ -31,7 +32,7 @@ import java.util.List; /** * @author Roman Chernyatchik */ -public class TestFailedState extends AbstractState { +public class TestFailedState extends AbstractState implements Disposable{ private final List myPresentationText; public TestFailedState(@Nullable final String localizedMessage, @@ -51,6 +52,9 @@ public class TestFailedState extends AbstractState { } } + @Override + public void dispose() {} + @Nullable public static String buildErrorPresentationText(@Nullable final String localizedMessage, @Nullable final String stackTrace) diff --git a/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/GeneralIdBasedToSMTRunnerEventsConvertorTest.java b/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/GeneralIdBasedToSMTRunnerEventsConvertorTest.java index 3363aa0f26a3..54e352199e94 100644 --- a/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/GeneralIdBasedToSMTRunnerEventsConvertorTest.java +++ b/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/GeneralIdBasedToSMTRunnerEventsConvertorTest.java @@ -124,7 +124,7 @@ public class GeneralIdBasedToSMTRunnerEventsConvertorTest extends BaseSMTRunnerT private void onTestFailed(@NotNull String id, @NotNull String errorMessage, int durationMillis) { myEventsProcessor.onTestFailure(new TestFailedEvent(null, id, errorMessage, null, false, null, - null, null, durationMillis)); + null, null, null, false, false, durationMillis)); } } diff --git a/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertorTest.java b/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertorTest.java index e702c6805ed1..d00284777b45 100644 --- a/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertorTest.java +++ b/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertorTest.java @@ -29,11 +29,14 @@ import com.intellij.execution.testframework.sm.runner.ui.SMTestRunnerResultsForm import com.intellij.execution.testframework.ui.TestsOutputConsolePrinter; import com.intellij.execution.ui.ConsoleViewContentType; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.io.FileUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreeModel; +import java.io.File; +import java.io.IOException; import java.io.StringReader; import java.util.List; @@ -46,6 +49,7 @@ public class GeneralToSMTRunnerEventsConvertorTest extends BaseSMTRunnerTestCase private TreeModel myTreeModel; private SMTestRunnerResultsForm myResultsViewer; private MockPrinter myMockResettablePrinter; + private File myTempFile; private class MyConsoleView extends SMTRunnerConsoleView { private final TestsOutputConsolePrinter myTestsOutputConsolePrinter; @@ -96,6 +100,10 @@ public class GeneralToSMTRunnerEventsConvertorTest extends BaseSMTRunnerTestCase Disposer.dispose(myConsole); super.tearDown(); + + if (myTempFile != null) { + assertFalse(myTempFile.exists()); + } } public void testOnStartedTesting() { @@ -177,6 +185,21 @@ public class GeneralToSMTRunnerEventsConvertorTest extends BaseSMTRunnerTestCase assertFalse(proxy.isInProgress()); } + public void testOnTestComparisonFailureLongExpectedText() throws IOException { + onTestStarted("some_test"); + myTempFile = FileUtil.createTempFile("expected", ""); + FileUtil.writeToFile(myTempFile, "expected text"); + myEventsProcessor.onTestFailure(new TestFailedEvent("some_test", "", "", null, false, "actual", + "expected", myTempFile.getCanonicalPath(), null, true, false, -1)); + + final String fullName = myEventsProcessor.getFullTestName("some_test"); + final SMTestProxy proxy = myEventsProcessor.getProxyByFullTestName(fullName); + + assertNotNull(proxy); + assertTrue(proxy.isDefect()); + assertFalse(proxy.isInProgress()); + } + public void testOnTestTruncatedComparisonFailure() { onTestStarted("some_test"); myEventsProcessor.onTestFailure(new TestFailedEvent("some_test", "", "", false, "actual", null));