Skip to content

Commit

Permalink
exclude errors by parts of stack trace (#263)
Browse files Browse the repository at this point in the history
* exclude errors by parts of stack trace

* PR fixes - improve code readability

* Fixed logic for including error messages by validator

* added unit tests for error validator

* added newlines at the end of resources files

* change ( ) to { } for better look

* fix code formatting

* PR fixes - improve code style in tests

* deleted unused resources files from tests

* PR fixes - improve code style and remove unnecessary assertions

* PR fixes - move config from file to string

* PR fixes - use flatMap instead of map for the win
  • Loading branch information
LukaszKontowski authored Sep 2, 2022
1 parent 5c43458 commit ace139a
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package org.virtuslab.ideprobe.reporting

import scala.collection.mutable

import org.virtuslab.ideprobe.config.CheckConfig
import org.virtuslab.ideprobe.protocol.IdeMessage

object ErrorValidator {
def apply(config: CheckConfig, errors: Seq[IdeMessage]): Option[Exception] = {
val filteredErrors = errors
.filter(error => config.errors.includeMessages.exists(_.r.findFirstIn(error.content).nonEmpty))
.filterNot(error => config.errors.excludeMessages.exists(_.r.findFirstIn(error.content).nonEmpty))
.filter(error => ideMessageMatchesMessagesFromConfig(error, config.errors.includeMessages))
.filterNot(error => ideMessageMatchesMessagesFromConfig(error, config.errors.excludeMessages))
if (filteredErrors.isEmpty) None
else {
println(toString(filteredErrors))
Expand All @@ -18,8 +20,16 @@ object ErrorValidator {
}
}

private def ideMessageMatchesMessagesFromConfig(ideMessage: IdeMessage, messagesFromConfig: Seq[String]): Boolean =
messagesFromConfig.exists { configMessage =>
trimEachLine(ideMessage.content).contains(trimEachLine(configMessage)) ||
configMessage.r.findFirstIn(ideMessage.content).nonEmpty
}

private def trimEachLine(s: String): String = s.linesIterator.map(_.trim).mkString("\n")

private def toString(errors: Seq[IdeMessage]): String = {
val sb = new StringBuilder()
val sb = new mutable.StringBuilder()

errors.groupBy(_.pluginId.getOrElse("IDEA")).foreach { case (group, errors) =>
sb.append(s"Errors caused by $group >>>\n")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package org.virtuslab.ideprobe.dependencies

import org.junit.Assert._
import org.junit.Test

import org.virtuslab.ideprobe.Config
import org.virtuslab.ideprobe.IntelliJFixture
import org.virtuslab.ideprobe.config.CheckConfig
import org.virtuslab.ideprobe.protocol.IdeMessage
import org.virtuslab.ideprobe.protocol.IdeMessage.Level
import org.virtuslab.ideprobe.reporting.ErrorValidator

class ErrorValidatorTest {
private val configRoot = "probe"
private val defaultConfigWithErrorsEnabled: Config = Config.fromString("probe.driver.check.errors.enabled = true")
private val defaultCheckConfigWithErrorsEnabled: CheckConfig =
IntelliJFixture.readIdeProbeConfig(defaultConfigWithErrorsEnabled, configRoot).driver.check

private val messageBusConnectionImplNPE =
"""
|java.lang.NullPointerException
| at com.intellij.util.messages.impl.MessageBusConnectionImpl.deliverImmediately(MessageBusConnectionImpl.java:61)
| at com.intellij.psi.impl.file.impl.FileManagerImpl.dispatchPendingEvents(FileManagerImpl.java:311)
| at com.intellij.psi.impl.file.impl.FileManagerImpl.getCachedPsiFile(FileManagerImpl.java:378)
| at com.intellij.psi.impl.PsiDocumentManagerBase.getCachedPsiFile(PsiDocumentManagerBase.java:143)
| at com.intellij.psi.impl.PsiDocumentManagerImpl$1.lambda$fileContentLoaded$0(PsiDocumentManagerImpl.java:55)
| at com.intellij.openapi.application.impl.ApplicationImpl.runReadAction(ApplicationImpl.java:865)
| at com.intellij.openapi.application.ReadAction.compute(ReadAction.java:61)
| at com.intellij.psi.impl.PsiDocumentManagerImpl$1.fileContentLoaded(PsiDocumentManagerImpl.java:55)
| at com.intellij.util.messages.impl.MessageBusImpl.invokeMethod(MessageBusImpl.java:645)
| at com.intellij.util.messages.impl.MessageBusImpl.invokeListener(MessageBusImpl.java:620)
| at com.intellij.util.messages.impl.MessageBusImpl.deliverMessage(MessageBusImpl.java:417)
| at com.intellij.util.messages.impl.MessageBusImpl.pumpWaitingBuses(MessageBusImpl.java:390)
| at com.intellij.util.messages.impl.MessageBusImpl.pumpMessages(MessageBusImpl.java:372)
| at com.intellij.util.messages.impl.MessageBusImpl.access$200(MessageBusImpl.java:33)
| at com.intellij.util.messages.impl.MessageBusImpl$MessagePublisher.invoke(MessageBusImpl.java:179)
| at com.sun.proxy.$Proxy137.suspendableProgressAppeared(Unknown Source)
| at com.intellij.openapi.progress.impl.ProgressSuspender.<init>(ProgressSuspender.java:61)
| at com.intellij.openapi.progress.impl.ProgressSuspender.markSuspendable(ProgressSuspender.java:77)
| at com.intellij.openapi.project.DumbServiceImpl.runBackgroundProcess(DumbServiceImpl.java:604)
| at com.intellij.openapi.project.DumbServiceImpl$5.run(DumbServiceImpl.java:587)
| at com.intellij.openapi.progress.impl.CoreProgressManager.startTask(CoreProgressManager.java:436)
| at com.intellij.openapi.progress.impl.ProgressManagerImpl.startTask(ProgressManagerImpl.java:120)
| at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcessWithProgressAsync$5(CoreProgressManager.java:496)
| at com.intellij.openapi.progress.impl.ProgressRunner.lambda$submit$3(ProgressRunner.java:244)
| at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$runProcess$2(CoreProgressManager.java:188)
| at com.intellij.openapi.progress.impl.CoreProgressManager.lambda$executeProcessUnderProgress$12(CoreProgressManager.java:624)
| at com.intellij.openapi.progress.impl.CoreProgressManager.registerIndicatorAndRun(CoreProgressManager.java:698)
| at com.intellij.openapi.progress.impl.CoreProgressManager.computeUnderProgress(CoreProgressManager.java:646)
| at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:623)
| at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:66)
| at com.intellij.openapi.progress.impl.CoreProgressManager.runProcess(CoreProgressManager.java:175)
| at com.intellij.openapi.progress.impl.ProgressRunner.lambda$submit$4(ProgressRunner.java:244)
| at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1700)
| at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
| at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
| at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:668)
| at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1$1.run(Executors.java:665)
| at java.base/java.security.AccessController.doPrivileged(Native Method)
| at java.base/java.util.concurrent.Executors$PrivilegedThreadFactory$1.run(Executors.java:665)
| at java.base/java.lang.Thread.run(Thread.java:829)
|""".stripMargin

private val uastMetaLanguageNPE =
"""
|java.lang.NullPointerException
| at com.intellij.uast.UastMetaLanguage.matchesLanguage(UastMetaLanguage.java:38)
| at com.intellij.codeInsight.daemon.impl.JavaColorProvider.getColorFrom(JavaColorProvider.java:39)
| at com.intellij.ui.ColorLineMarkerProvider.lambda$getLineMarkerInfo$0(ColorLineMarkerProvider.java:39)
| at com.intellij.openapi.extensions.impl.ExtensionProcessingHelper.computeSafeIfAny(ExtensionProcessingHelper.java:55)
| at com.intellij.openapi.extensions.ExtensionPointName.computeSafeIfAny(ExtensionPointName.java:57)
| at com.intellij.ui.ColorLineMarkerProvider.getLineMarkerInfo(ColorLineMarkerProvider.java:38)
| at com.intellij.codeInsight.daemon.impl.LineMarkersPass.queryProviders(LineMarkersPass.java:158)
| at com.intellij.codeInsight.daemon.impl.LineMarkersPass.lambda$doCollectInformation$3(LineMarkersPass.java:83)
| at com.intellij.codeInsight.daemon.impl.Divider.divideInsideAndOutsideInOneRoot(Divider.java:81)
| at com.intellij.codeInsight.daemon.impl.LineMarkersPass.doCollectInformation(LineMarkersPass.java:78)
| at com.intellij.codeHighlighting.TextEditorHighlightingPass.collectInformation(TextEditorHighlightingPass.java:56)
| at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.lambda$doRun$1(PassExecutorService.java:400)
| at com.intellij.openapi.application.impl.ApplicationImpl.tryRunReadAction(ApplicationImpl.java:1137)
| at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.lambda$doRun$2(PassExecutorService.java:393)
| at com.intellij.openapi.progress.impl.CoreProgressManager.registerIndicatorAndRun(CoreProgressManager.java:658)
| at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:610)
| at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:65)
| at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.doRun(PassExecutorService.java:392)
| at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.lambda$run$0(PassExecutorService.java:368)
| at com.intellij.openapi.application.impl.ReadMostlyRWLock.executeByImpatientReader(ReadMostlyRWLock.java:172)
| at com.intellij.openapi.application.impl.ApplicationImpl.executeByImpatientReader(ApplicationImpl.java:183)
| at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.run(PassExecutorService.java:366)
| at com.intellij.concurrency.JobLauncherImpl$VoidForkJoinTask$1.exec(JobLauncherImpl.java:188)
| at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
| at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
| at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
| at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
| at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)
|""".stripMargin

private val errorIdeMessages: List[IdeMessage] = List(messageBusConnectionImplNPE, uastMetaLanguageNPE)
.map(content => IdeMessage(Level.Error, content, pluginId = None))

private val messageBusSpecificString = "at com.intellij.util.messages.impl.MessageBusConnectionImpl"
private val uastMetaSpecificString = "at com.intellij.uast.UastMetaLanguage"

@Test
def shouldIncludeAllErrorsByDefault(): Unit = {
val exceptions: List[Exception] = collectExceptions(defaultCheckConfigWithErrorsEnabled)
assertEquals(2, exceptions.size)
}

@Test
def shouldIgnoreAllErrorsIfNotEnabled(): Unit = {
val checkConfigErrorsDisabled = defaultCheckConfigWithErrorsEnabled.copy(
errors = defaultCheckConfigWithErrorsEnabled.errors.copy(enabled = false)
)
val exceptions: List[Exception] = collectExceptions(checkConfigErrorsDisabled)
assertEquals(0, exceptions.size)
}

@Test
def shouldIncludeOnlySpecificErrorsIfIncludeMessagesConfigured(): Unit = {
val checkConfigForMessageBusErrorsOnly = defaultCheckConfigWithErrorsEnabled.copy(
errors = defaultCheckConfigWithErrorsEnabled.errors.copy(includeMessages = Seq(s".*$messageBusSpecificString.*"))
)
val exceptions: List[Exception] = collectExceptions(checkConfigForMessageBusErrorsOnly)
assertEquals(1, exceptions.size)
assertTrue(exceptions.head.getMessage.contains(messageBusSpecificString))
}

@Test
def shouldExcludeSpecificErrorsByRegexUsage(): Unit = {
val checkConfigToIgnoreMessageBusErrors = defaultCheckConfigWithErrorsEnabled.copy(
errors = defaultCheckConfigWithErrorsEnabled.errors.copy(excludeMessages = Seq(s".*$messageBusSpecificString.*"))
)
val exceptions: List[Exception] = collectExceptions(checkConfigToIgnoreMessageBusErrors)
assertEquals(1, exceptions.size)
assertFalse(exceptions.head.getMessage.contains(messageBusSpecificString))
assertTrue(exceptions.head.getMessage.contains(uastMetaSpecificString))
}

@Test
def shouldExcludeErrorsByPartsOfStackTrace(): Unit = {
val partOfMessageBusStackTrace =
"""
|at com.intellij.util.messages.impl.MessageBusConnectionImpl.deliverImmediately(MessageBusConnectionImpl.java:61)
| at com.intellij.psi.impl.file.impl.FileManagerImpl.dispatchPendingEvents(FileManagerImpl.java:311)
| at com.intellij.psi.impl.file.impl.FileManagerImpl.getCachedPsiFile(FileManagerImpl.java:378)
| at com.intellij.psi.impl.PsiDocumentManagerBase.getCachedPsiFile(PsiDocumentManagerBase.java:143)
|""".stripMargin
val checkConfigToIgnoreMessageBusErrors = defaultCheckConfigWithErrorsEnabled.copy(
errors = defaultCheckConfigWithErrorsEnabled.errors.copy(excludeMessages = Seq(partOfMessageBusStackTrace))
)
val exceptions: List[Exception] = collectExceptions(checkConfigToIgnoreMessageBusErrors)
assertEquals(1, exceptions.size)
assertFalse(exceptions.head.getMessage.contains(messageBusSpecificString))
assertTrue(exceptions.head.getMessage.contains(uastMetaSpecificString))
}

private def collectExceptions(checkConfig: CheckConfig): List[Exception] =
errorIdeMessages.flatMap(msg => ErrorValidator(checkConfig, Seq(msg)))

}

0 comments on commit ace139a

Please sign in to comment.