Workarounds for Kotlin flaky resolve (KT-40998)
[idea/community.git] / java / testFramework / src / com / intellij / testFramework / fixtures / kotlin / KtFlakyErrorWorkaround.kt
1 package com.intellij.testFramework.fixtures.kotlin
2
3 import com.intellij.openapi.diagnostic.logger
4
5 class KtFlakyErrorWorkaround(private val setUp: () -> Unit,
6                              private val tearDown: () -> Unit,
7                              private val repeatCount: Int = 5) {
8
9   fun wrapFlaky(actualMessagePattern: Regex, body: () -> Unit): Unit =
10     repeatTest({ e -> e is AssertionError && e.actual.contains(actualMessagePattern) }, body)
11
12   fun wrapFlaky(actualMessagePattern: Regex, body: Runnable): Unit = wrapFlaky(actualMessagePattern) { body.run() }
13
14   fun repeatTest(repeatCondition: (Throwable) -> Boolean = { true }, body: () -> Unit) {
15     var repeat: Boolean
16     var repeatedTimes = 0
17     do {
18       try {
19         body()
20         repeat = false
21       }
22       catch (e: Throwable) {
23         if (repeatCondition(e)) {
24           logger<KtFlakyErrorWorkaround>().warn("Workaround hit! ${e.javaClass} on try: $repeatedTimes")
25           repeatedTimes++
26           repeat = true
27           if (repeatedTimes > repeatCount) {
28             logger<KtFlakyErrorWorkaround>().error("Workaround: hit too many times: $repeatedTimes, max is $repeatCount")
29             throw e
30           }
31           tearDown()
32           setUp()
33         }
34         else {
35           throw e
36         }
37       }
38     }
39     while (repeat)
40   }
41
42   private val AssertionError.actual: String
43     get() = when (this) {
44       is org.junit.ComparisonFailure -> this.actual
45       is junit.framework.ComparisonFailure -> this.actual
46       else -> ""
47     }
48
49 }