From 8e4de4c726bbe21c5a83bb993ae8d5749ac1619b Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Tue, 21 Feb 2017 11:56:08 +0300 Subject: [PATCH] workaround for blinking tests because of JVMTI_ERROR_WRONG_PHASE(112) --- .../intellij/debugger/DebuggerTestCase.java | 40 ++++++++++++++++++- .../intellij/debugger/impl/OutputChecker.java | 6 ++- .../testFramework/UsefulTestCase.java | 32 ++++++++++----- 3 files changed, 65 insertions(+), 13 deletions(-) diff --git a/java/testFramework/src/com/intellij/debugger/DebuggerTestCase.java b/java/testFramework/src/com/intellij/debugger/DebuggerTestCase.java index 3e79a2b0a849..99c8f23835cf 100644 --- a/java/testFramework/src/com/intellij/debugger/DebuggerTestCase.java +++ b/java/testFramework/src/com/intellij/debugger/DebuggerTestCase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -39,6 +39,7 @@ import com.intellij.execution.process.ProcessOutputTypes; import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.execution.runners.ExecutionEnvironmentBuilder; import com.intellij.execution.runners.ProgramRunner; +import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; @@ -55,6 +56,7 @@ import com.intellij.psi.PsiClass; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.util.ThrowableRunnable; import com.intellij.util.ui.UIUtil; import com.intellij.xdebugger.XDebugProcess; import com.intellij.xdebugger.XDebugProcessStarter; @@ -67,10 +69,14 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.lang.reflect.InvocationTargetException; import java.util.StringTokenizer; +import java.util.concurrent.atomic.AtomicInteger; public abstract class DebuggerTestCase extends ExecutionWithDebuggerToolsTestCase { public static final int DEFAULT_ADDRESS = 3456; protected DebuggerSession myDebuggerSession; + protected final AtomicInteger myRestart = new AtomicInteger(); + private static final int MAX_RESTARTS = 3; + private volatile TestDisposable myTestRootDisposable; @Override protected void initApplication() throws Exception { @@ -93,10 +99,42 @@ public abstract class DebuggerTestCase extends ExecutionWithDebuggerToolsTestCas assertNull(DebuggerManagerEx.getInstanceEx(myProject).getDebugProcess(getDebugProcess().getProcessHandler())); myDebuggerSession = null; } + + if (getChecker().contains("JVMTI_ERROR_WRONG_PHASE(112)")) { + myRestart.incrementAndGet(); + if (needsRestart()) { + return; + } + } else { + myRestart.set(0); + } + throwExceptionsIfAny(); checkTestOutput(); } + private boolean needsRestart() { + int restart = myRestart.get(); + return restart > 0 && restart <= MAX_RESTARTS; + } + + @Override + protected void runBareRunnable(ThrowableRunnable runnable) throws Throwable { + myTestRootDisposable = new TestDisposable(); + super.runBareRunnable(runnable); + while (needsRestart()) { + assert (myTestRootDisposable.isDisposed()); + myTestRootDisposable = new TestDisposable(); + super.runBareRunnable(runnable); + } + } + + @NotNull + @Override + public Disposable getTestRootDisposable() { + return myTestRootDisposable; + } + protected void checkTestOutput() throws Exception { getChecker().checkValid(getTestProjectJdk()); } diff --git a/java/testFramework/src/com/intellij/debugger/impl/OutputChecker.java b/java/testFramework/src/com/intellij/debugger/impl/OutputChecker.java index 4c23389816c8..7f1a78121f1a 100644 --- a/java/testFramework/src/com/intellij/debugger/impl/OutputChecker.java +++ b/java/testFramework/src/com/intellij/debugger/impl/OutputChecker.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -157,6 +157,10 @@ public class OutputChecker { } } + public boolean contains(String str) { + return buildOutputString().contains(str); + } + private synchronized String buildOutputString() { final StringBuilder result = new StringBuilder(); for (Key key : OUTPUT_ORDER) { diff --git a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java index ac7eb66891db..fded6c161434 100644 --- a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java @@ -88,16 +88,7 @@ public abstract class UsefulTestCase extends TestCase { } @NotNull - private final Disposable myTestRootDisposable = new Disposable() { - @Override - public void dispose() { } - - @Override - public String toString() { - String testName = getTestName(false); - return UsefulTestCase.this.getClass() + (StringUtil.isEmpty(testName) ? "" : ".test" + testName); - } - }; + private final Disposable myTestRootDisposable = new TestDisposable(); static String ourPathToKeep; private final List myPathsToKeep = new ArrayList<>(); @@ -307,7 +298,7 @@ public abstract class UsefulTestCase extends TestCase { } @NotNull - public final Disposable getTestRootDisposable() { + public Disposable getTestRootDisposable() { return myTestRootDisposable; } @@ -1000,4 +991,23 @@ public abstract class UsefulTestCase extends TestCase { @Deprecated public static final String IDEA_MARKER_CLASS = "com.intellij.openapi.roots.IdeaModifiableModelsProvider"; // + + public class TestDisposable implements Disposable { + private volatile boolean myDisposed; + + @Override + public void dispose() { + myDisposed = true; + } + + public boolean isDisposed() { + return myDisposed; + } + + @Override + public String toString() { + String testName = getTestName(false); + return UsefulTestCase.this.getClass() + (StringUtil.isEmpty(testName) ? "" : ".test" + testName); + } + } } \ No newline at end of file