optimize protocol with long lines printed into system out; cut out too long output before parsing control messages to avoid OOME and produce testSuccessful instead of testFailure (IDEA-158222)

This commit is contained in:
Anna.Kozlova
2016-07-12 11:08:35 +02:00
parent 67303f7455
commit 34343c165d
3 changed files with 29 additions and 2 deletions
@@ -159,6 +159,7 @@ public abstract class OutputLineSplitter {
private static class OutputChunk {
private final Key myKey;
private String myText;
private StringBuilder myBuilder;
private OutputChunk(Key key, String text) {
myKey = key;
@@ -170,11 +171,19 @@ public abstract class OutputLineSplitter {
}
public String getText() {
if (myBuilder != null) {
myText = myBuilder.toString();
myBuilder = null;
}
return myText;
}
public void append(String text) {
myText += text;
if (myBuilder == null) {
myBuilder = new StringBuilder(myText);
myText = null;
}
myBuilder.append(text);
}
}
}
@@ -15,6 +15,7 @@
*/
package com.intellij.execution.testframework.sm.runner;
import com.intellij.execution.impl.ConsoleBuffer;
import com.intellij.execution.process.ProcessOutputTypes;
import com.intellij.execution.testframework.TestConsoleProperties;
import com.intellij.execution.testframework.sm.runner.events.*;
@@ -41,6 +42,7 @@ import static com.intellij.execution.testframework.sm.runner.GeneralToSMTRunnerE
*/
public class OutputToGeneralTestEventsConverter implements ProcessOutputConsumer {
private static final Logger LOG = Logger.getInstance(OutputToGeneralTestEventsConverter.class.getName());
private final int CYCLE_BUFFER_SIZE = ConsoleBuffer.getCycleBufferSize();
private final MyServiceMessageVisitor myServiceMessageVisitor;
private final String myTestFrameworkName;
@@ -90,7 +92,15 @@ public class OutputToGeneralTestEventsConverter implements ProcessOutputConsumer
fireOnUncapturedOutput("\n", ProcessOutputTypes.STDOUT);
}
private void processConsistentText(final String text, final Key outputType, boolean tcLikeFakeOutput) {
private void processConsistentText(String text, final Key outputType, boolean tcLikeFakeOutput) {
if (text.length() > CYCLE_BUFFER_SIZE) {
final StringBuilder builder = new StringBuilder(CYCLE_BUFFER_SIZE);
builder.append(text, 0, CYCLE_BUFFER_SIZE - 105);
builder.append("<...>");
builder.append(text, text.length() - 100, text.length());
text = builder.toString();
}
try {
if (!processServiceMessages(text, outputType, myServiceMessageVisitor)) {
if (myPendingLineBreakFlag) {
@@ -21,6 +21,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.testFramework.PlatformTestCase;
import com.intellij.testFramework.PlatformTestUtil;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull;
@@ -178,6 +179,13 @@ public class OutputLineSplitterTest extends PlatformTestCase {
}
}
public void testPerformanceWithLotsOfFragments() throws Exception {
for (int i = 0; i < 10_000; i++) {
mySplitter.process("some string without slash n appending in raw, attempt: " + i + "; ", ProcessOutputTypes.STDOUT);
}
PlatformTestUtil.startPerformanceTest("Flashing lot's of fragments", 10, mySplitter::flush).attempts(1).useLegacyScaling().assertTiming();
}
private Future<?> execute(final Runnable runnable) {
return ApplicationManager.getApplication().executeOnPooledThread(runnable);
}