scalameta/munit

Request: Move FunSuite.unitTimeout to trait, to support stackable overriding trait

dsbos opened this issue · 0 comments

dsbos commented

Can you move FunSuite.munitTimeout out to a separate trait, to better support stackable overriding?

I'd like to do something like the code below, but without extending FunSuite (so the client code (the extending test class) is still responsible for separately pulling in FunSuite).

package whatever

import scala.concurrent.duration.Duration

// ?? TODO:  If MUnit factors munitTimeout out of class FunSuite into a separate
//  trait (supporting stackable overriding), adjust the `extends munit.FunSuite`
//  and `this: munit.FunSuite =>` part to refer to that trait.

/** Mix-in to disable MUnit timeouts when running under a debugger.
  *
  * Note:  This _will not take effect_ if a client test class overrides `munit.FunSuite.unitTimeout` to a fixed value.
  * However, it can still take effect if the client derives the final munitTimeout value in terms of `super.munitTimeout`.
  * For example, a client could use `override val munitTimeout = super.munitTimeout * 2` (to use double the default
  * timeout), because method `Duration.*` is smart about `Duration.Inf`.
  *
  */
trait DisableMunitTimeoutsUnderDebugger extends munit.FunSuite {
  this: munit.FunSuite =>

  private val startedUnderDebugger: Boolean = {
    import scala.jdk.CollectionConverters._ // for .asScala

    val runtimeBean = java.lang.management.ManagementFactory.getRuntimeMXBean
    val jvmArgs = runtimeBean.getInputArguments.asScala
    jvmArgs.exists { arg => arg.startsWith("-agentlib:jdwp") || arg.startsWith("-Xrunjdwp") }
  }

  abstract override def munitTimeout: Duration = {
    if (!startedUnderDebugger) {
      // Normally use default timeout:
      super.munitTimeout
    } else {
      println("Debugger detected; overriding munitTimeout to infinity")
      Duration.Inf
    }
  }
}