All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.io.kotest.assertions.Retry.kt Maven / Gradle / Ivy

package io.kotest.assertions

import io.kotest.mpp.bestName
import kotlinx.coroutines.delay
import kotlin.reflect.KClass
import kotlin.time.Duration
import kotlin.time.DurationUnit
import kotlin.time.ExperimentalTime
import kotlin.time.TimeSource

/**
 * Retry the given lambda [f] in case of assertion error[AssertionError] and exception [Exception].
 * Stops trying when [maxRetry] or [timeout] is reached.
 * */
@OptIn(ExperimentalTime::class)
suspend fun  retry(
   maxRetry: Int,
   timeout: Duration,
   delay: Duration = timeout,
   multiplier: Int = 1,
   f: () -> T
): T = retry(maxRetry, timeout, delay, multiplier, Exception::class, f)


/**
 * Retry the given lambda [f] in case of assertion error[AssertionError] and exception of type [exceptionClass].
 * Stops trying when [maxRetry] or [timeout] is reached. Or an exception other than [exceptionClass] is thrown
 * */
@OptIn(ExperimentalTime::class)
suspend fun  retry(
   maxRetry: Int,
   timeout: Duration,
   delay: Duration = timeout,
   multiplier: Int = 1,
   exceptionClass: KClass,
   f: () -> T
): T {
   val mark = TimeSource.Monotonic.markNow()
   val end = mark.plus(timeout)
   var retrySoFar = 0
   var nextAwaitDuration = delay.toLongMilliseconds()
   var lastError: Throwable? = null

   while (end.hasNotPassedNow() && retrySoFar < maxRetry) {
      try {
         return f()
      } catch (e: Throwable) {
         when {
            // Not the kind of exceptions we were prepared to tolerate
            e::class.simpleName != "AssertionError" &&
               e::class != exceptionClass &&
               e::class.bestName() != "org.opentest4j.AssertionFailedError" -> throw e
         }
         lastError = e
         // else ignore and continue
      }
      retrySoFar++
      delay(nextAwaitDuration)
      nextAwaitDuration *= multiplier
   }
   val underlyingCause = if (lastError == null) "" else "; underlying cause was ${lastError.message}"
   throw failure(
      "Test failed after ${delay.toLong(DurationUnit.SECONDS)} seconds; attempted $retrySoFar times$underlyingCause",
      lastError
   )
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy