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

jvmTest.io.kotest.framework.concurrency.IntervalSpec.kt Maven / Gradle / Ivy

package io.kotest.framework.concurrency

import io.kotest.assertions.all
import io.kotest.common.ExperimentalKotest
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.comparables.shouldBeGreaterThan
import io.kotest.matchers.comparables.shouldBeGreaterThanOrEqualTo
import io.kotest.matchers.comparables.shouldBeLessThan
import io.kotest.matchers.shouldBe
import kotlin.math.pow
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.minutes
import kotlin.time.Duration.Companion.seconds

@ExperimentalKotest
class IntervalSpec : FunSpec({
   context("fixed interval") {
      test("always returns the same value") {
         val expected = 25L
         val interval = expected.fixed()

         (0..100).forEach { interval.next(it) shouldBe 25L }
      }
   }

   context("exponential interval") {
      test("has a reasonable default next") {
         val identity = 2.seconds.inWholeMilliseconds

         all(identity.exponential()) {
            next(0) shouldBe identity * 1
            next(1) shouldBe identity * 2
            next(2) shouldBe identity * 4
         }

         all(identity.exponential(factor = 3.0)) {
            next(0) shouldBe identity * 1
            next(1) shouldBe identity * 3
            next(2) shouldBe identity * 9
         }
      }

      test("has a reasonable default max") {
         val max = ExponentialInterval.defaultMax
         val default = 25.milliseconds.inWholeMilliseconds.exponential()
         val unbounded = 25.milliseconds.inWholeMilliseconds.exponential(max = null)

         val first = 0
         val last = 20

         unbounded.next(first) shouldBeLessThan max
         unbounded.next(last) shouldBeGreaterThan max

         for (i in first..last) {
            val u = unbounded.next(i)
            val d = default.next(i)

            if (u < max) {
               d shouldBe u
            } else {
               d shouldBe max
               u shouldBeGreaterThan max
            }
         }
      }

      test("respects user specified max") {
         val base = 25.milliseconds.inWholeMilliseconds
         val n = 5
         val max = base * ExponentialInterval.defaultFactor.pow(n).toLong()
         val bounded = base.exponential(max = max)
         val unbounded = base.exponential(max = null)

         val first = 0
         val last = 20

         unbounded.next(first) shouldBeLessThan max
         unbounded.next(last) shouldBeGreaterThan max

         for (i in first..last) {
            val u = unbounded.next(i)
            val b = bounded.next(i)

            if (u < max) {
               b shouldBe u
               i shouldBeLessThan n
            } else {
               i shouldBeGreaterThanOrEqualTo n
               b shouldBe max
               u shouldBeGreaterThanOrEqualTo max
            }
         }
      }
   }

   context("fibonacci interval") {
      test("correctness") {
         fibonacci(0) shouldBe 0
         fibonacci(1) shouldBe 1
         fibonacci(2) shouldBe 1
         fibonacci(3) shouldBe 2
         fibonacci(4) shouldBe 3
         fibonacci(5) shouldBe 5
         fibonacci(6) shouldBe 8
         fibonacci(7) shouldBe 13
      }

      test("has a reasonable default max") {
         val max = FibonacciInterval.defaultMax
         val default = 10.minutes.inWholeMilliseconds.fibonacci()
         val unbounded = 10.minutes.inWholeMilliseconds.fibonacci(null)

         val first = 0
         val last = 20

         unbounded.next(first) shouldBeLessThan max
         unbounded.next(last) shouldBeGreaterThan max

         for (i in first..last) {
            val u = unbounded.next(i)
            val d = default.next(i)

            if (u < max) {
               d shouldBe u
            } else {
               d shouldBe max
               u shouldBeGreaterThan max
            }
         }
      }

      test("respects user specified max") {
         val max = FibonacciInterval.defaultMax + 15.minutes.inWholeMilliseconds
         val bounded = 10.minutes.inWholeMilliseconds.fibonacci(max)
         val unbounded = 10.minutes.inWholeMilliseconds.fibonacci(null)

         val first = 0
         val last = 20

         unbounded.next(first) shouldBeLessThan max
         unbounded.next(last) shouldBeGreaterThan max

         for (i in first..last) {
            val u = unbounded.next(i)
            val b = bounded.next(i)

            if (u < max) {
               b shouldBe u
            } else {
               b shouldBe max
               u shouldBeGreaterThan max
            }
         }
      }
   }
})




© 2015 - 2025 Weber Informatics LLC | Privacy Policy