diff --git a/java/testFramework/src/com/intellij/execution/ExecutionTestCase.java b/java/testFramework/src/com/intellij/execution/ExecutionTestCase.java index 965c09198d86..600ee0253907 100644 --- a/java/testFramework/src/com/intellij/execution/ExecutionTestCase.java +++ b/java/testFramework/src/com/intellij/execution/ExecutionTestCase.java @@ -57,6 +57,10 @@ public abstract class ExecutionTestCase extends JavaProjectTestCase { protected abstract String getTestAppPath(); + protected boolean areLogErrorsIgnored() { + return false; + } + @Override protected void setUp() throws Exception { setupTempDir(); @@ -139,9 +143,14 @@ public abstract class ExecutionTestCase extends JavaProjectTestCase { myChecker.print(s, outputType); } + @SuppressWarnings("CallToPrintStackTrace") @Override protected void runBareRunnable(@NotNull ThrowableRunnable runnable) throws Throwable { runnable.run(); + int errorLoggingHappened = TestLoggerFactory.getRethrowErrorNumber(); + if (errorLoggingHappened != 0 && !areLogErrorsIgnored()) { + assertEquals("No ignored errors should happen during execution tests", 0, errorLoggingHappened); + } } @Override diff --git a/platform/testFramework/core/src/com/intellij/testFramework/TestLoggerFactory.java b/platform/testFramework/core/src/com/intellij/testFramework/TestLoggerFactory.java index cbdb5c14909a..dae22a3bd37c 100644 --- a/platform/testFramework/core/src/com/intellij/testFramework/TestLoggerFactory.java +++ b/platform/testFramework/core/src/com/intellij/testFramework/TestLoggerFactory.java @@ -28,6 +28,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.List; import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; import java.util.logging.LogManager; import java.util.logging.LogRecord; @@ -59,6 +60,8 @@ public final class TestLoggerFactory implements Logger.Factory { /** When enabled, log records with at least "FINE" level are echoed to the stdout with a timestamp relative to the test start time. */ private static final boolean myEchoDebugToStdout = Boolean.getBoolean("idea.test.logs.echo.debug.to.stdout"); + private static final AtomicInteger myRethrowErrorsNumber = new AtomicInteger(0); + private TestLoggerFactory() { } private static @Nullable TestLoggerFactory getTestLoggerFactory() { @@ -90,6 +93,10 @@ public final class TestLoggerFactory implements Logger.Factory { } } + public static @NotNull int getRethrowErrorNumber() { + return myRethrowErrorsNumber.get(); + } + public static boolean reconfigure() { try { String customConfigPath = System.getProperty(PathManager.PROPERTY_LOG_CONFIG_FILE); @@ -249,6 +256,7 @@ public final class TestLoggerFactory implements Logger.Factory { } public static void onTestStarted() { + myRethrowErrorsNumber.set(0); TestLoggerFactory factory = getTestLoggerFactory(); if (factory != null) { factory.clearLogBuffer(); // clear buffer from tests which failed to report their termination properly @@ -401,6 +409,7 @@ public final class TestLoggerFactory implements Logger.Factory { } if (actions.contains(LoggedErrorProcessor.Action.RETHROW)) { + myRethrowErrorsNumber.incrementAndGet(); throw new TestLoggerAssertionError(message, t); } } diff --git a/plugins/kotlin/base/test/test/org/jetbrains/kotlin/idea/base/test/InTextDirectivesUtils.java b/plugins/kotlin/base/test/test/org/jetbrains/kotlin/idea/base/test/InTextDirectivesUtils.java index 07574e486421..2301cb3c8552 100644 --- a/plugins/kotlin/base/test/test/org/jetbrains/kotlin/idea/base/test/InTextDirectivesUtils.java +++ b/plugins/kotlin/base/test/test/org/jetbrains/kotlin/idea/base/test/InTextDirectivesUtils.java @@ -26,6 +26,7 @@ public final class InTextDirectivesUtils { public static final String IGNORE_BACKEND_DIRECTIVE_PREFIX = "// IGNORE_BACKEND: "; public static final String MUTED_DIRECTIVE_PREFIX = "// MUTED: "; public static final String IGNORE_FOR_K2_CODE = "// IGNORE_FOR_K2_CODE"; + public static final String IGNORE_LOG_ERRORS = "// IGNORE_LOG_ERRORS"; private InTextDirectivesUtils() { } @@ -262,6 +263,10 @@ public final class InTextDirectivesUtils { return backends.isEmpty() || backends.contains(targetBackend.name()) || isCompatibleTargetExceptAny(targetBackend.getCompatibleWith(), backends); } + public static boolean areLogErrorsIgnored(File file) { + return textWithDirectives(file).contains(IGNORE_LOG_ERRORS); + } + public static boolean isIgnoredTarget(TargetBackend targetBackend, File file, String ignoreBackendDirectivePrefix) { List ignoredBackends = findListWithPrefixes(textWithDirectives(file), ignoreBackendDirectivePrefix); return ignoredBackends.contains(targetBackend.name()); diff --git a/plugins/kotlin/jvm-debugger/test/test/org/jetbrains/kotlin/idea/debugger/test/KotlinDescriptorTestCaseWithStepping.kt b/plugins/kotlin/jvm-debugger/test/test/org/jetbrains/kotlin/idea/debugger/test/KotlinDescriptorTestCaseWithStepping.kt index a2bf570c90ab..68ebb02229ee 100644 --- a/plugins/kotlin/jvm-debugger/test/test/org/jetbrains/kotlin/idea/debugger/test/KotlinDescriptorTestCaseWithStepping.kt +++ b/plugins/kotlin/jvm-debugger/test/test/org/jetbrains/kotlin/idea/debugger/test/KotlinDescriptorTestCaseWithStepping.kt @@ -34,6 +34,7 @@ import junit.framework.AssertionFailedError import junit.framework.TestCase import org.jetbrains.idea.maven.aether.ArtifactKind import org.jetbrains.jps.model.library.JpsMavenRepositoryLibraryDescriptor +import org.jetbrains.kotlin.idea.base.test.InTextDirectivesUtils.areLogErrorsIgnored import org.jetbrains.kotlin.idea.base.test.InTextDirectivesUtils.isIgnoredTarget import org.jetbrains.kotlin.idea.debugger.KotlinPositionManager import org.jetbrains.kotlin.idea.debugger.core.stackFrame.KotlinStackFrame @@ -240,11 +241,15 @@ abstract class KotlinDescriptorTestCaseWithStepping : KotlinDescriptorTestCase() return outputStream.toString(StandardCharsets.UTF_8) } - protected fun isTestIgnored(): Boolean { + fun isTestIgnored(): Boolean { val outputFile = getExpectedOutputFile() return outputFile.exists() && isIgnoredTarget(targetBackend(), outputFile) } + override fun areLogErrorsIgnored(): Boolean { + return isTestIgnored() || areLogErrorsIgnored(dataFile()) + } + private fun SuspendContextImpl.printContext() { runReadAction { if (this.frameProxy == null) { diff --git a/plugins/kotlin/jvm-debugger/test/testData/evaluation/scripts/kt51755.kt b/plugins/kotlin/jvm-debugger/test/testData/evaluation/scripts/kt51755.kt index e31132d28858..d4e570f11376 100644 --- a/plugins/kotlin/jvm-debugger/test/testData/evaluation/scripts/kt51755.kt +++ b/plugins/kotlin/jvm-debugger/test/testData/evaluation/scripts/kt51755.kt @@ -24,3 +24,5 @@ class A(val x: String) { } } A("hoho").sum(12) + +// IGNORE_LOG_ERRORS diff --git a/plugins/kotlin/jvm-debugger/test/testData/stepping/custom/coroutine.kt b/plugins/kotlin/jvm-debugger/test/testData/stepping/custom/coroutine.kt index 85f429367145..385f6b4fdc18 100644 --- a/plugins/kotlin/jvm-debugger/test/testData/stepping/custom/coroutine.kt +++ b/plugins/kotlin/jvm-debugger/test/testData/stepping/custom/coroutine.kt @@ -19,3 +19,5 @@ fun main(args: Array) { first() } } + +// IGNORE_LOG_ERRORS