org.scalatest.concurrent

Timeouts

trait Timeouts extends AnyRef

Trait that provides a failAfter construct, which allows you to specify a time limit for an operation passed as a by-name parameter, as well as a way to interrupt it if the operation exceeds its time limit.

The time limit is passed as the first parameter, as a Span. The operation is passed as the second parameter. And an Interruptor, a strategy for interrupting the operation, is passed as an implicit third parameter. Here's a simple example of its use:

failAfter(Span(100, Millis)) {
  Thread.sleep(200)
}

The above code, after 100 milliseconds, will produce a TestFailedDueToTimeoutException with a message that indicates a timeout expired:

The code passed to failAfter did not complete within 100 milliseconds.

If you prefer you can mix in or import the members of SpanSugar and place a units value after the integer timeout. Here are some examples:

import org.scalatest.time.SpanSugar._

failAfter(100 millis) { Thread.sleep(200) }
failAfter(1 second) { Thread.sleep(2000) }

The code passed via the by-name parameter to failAfter will be executed by the thread that invoked failAfter, so that no synchronization is necessary to access variables declared outside the by-name.

var result = -1 // No need to make this volatile
failAfter(100 millis) {
  result = accessNetService()
}
result should be (99)

The failAfter method will create a timer that runs on a different thread than the thread that invoked failAfter, so that it can detect when the timeout has expired and attempt to interrupt the main thread. Because different operations can require different interruption strategies, the failAfter method accepts an implicit third parameter of type Interruptor that is responsible for interrupting the main thread.

Configuring failAfter with an Interruptor

This trait declares an implicit val named defaultInterruptor, initialized with a ThreadInterruptor, which attempts to interrupt the main thread by invoking Thread.interrupt. If you wish to use a different strategy, you can override this val (or hide it, for example if you imported the members of Timeouts rather than mixing it in). Here's an example in which the default interruption method is changed to DoNotInterrupt, which does not attempt to interrupt the main thread in any way:

override val defaultInterruptor = DoNotInterrupt
failAfter(100 millis) {
  Thread.sleep(500)
}

As with the default Interruptor, the above code will eventually produce a TestFailedDueToTimeoutException with a message that indicates a timeout expired. However, instead of throwing the exception after approximately 100 milliseconds, it will throw it after approximately 500 milliseconds.

This illustrates an important feature of failAfter: it will throw a TestFailedDueToTimeoutException if the code passed as the by-name parameter takes longer than the specified timeout to execute, even if it is allowed to run to completion beyond the specified timeout and returns normally.

ScalaTest provides the following Interruptor implementations:

Interruptor implementation Usage
ThreadInterruptor The default interruptor, invokes interrupt on the main test thread. This will set the interrupted status for the main test thread and, if the main thread is blocked, will in some cases cause the main thread complete abruptly with an InterruptedException.
DoNotInterrupt Does not attempt to interrupt the main test thread in any way
SelectorInterruptor Invokes wakeup on the passed java.nio.channels.Selector, which will cause the main thread, if blocked in Selector.select, to complete abruptly with a ClosedSelectorException.
SocketInterruptor Invokes close on the java.io.Socket, which will cause the main thread, if blocked in a read or write of an java.io.InputStream or java.io.OutputStream that uses the Socket, to complete abruptly with a SocketException.

You may wish to create your own Interruptor in some situations. For example, if your operation is performing a loop and can check a volatile flag each pass through the loop. You could in that case write an Interruptor that sets that flag so that the next time around, the loop would exit.

Linear Supertypes
AnyRef, Any
Known Subclasses
Ordering
  1. Alphabetic
  2. By inheritance
Inherited
  1. Hide All
  2. Show all
  1. Timeouts
  2. AnyRef
  3. Any
Visibility
  1. Public
  2. All

Value Members

  1. def != (arg0: AnyRef): Boolean

    Attributes
    final
    Definition Classes
    AnyRef
  2. def != (arg0: Any): Boolean

    Attributes
    final
    Definition Classes
    Any
  3. def ## (): Int

    Attributes
    final
    Definition Classes
    AnyRef → Any
  4. def == (arg0: AnyRef): Boolean

    Attributes
    final
    Definition Classes
    AnyRef
  5. def == (arg0: Any): Boolean

    Attributes
    final
    Definition Classes
    Any
  6. def asInstanceOf [T0] : T0

    Attributes
    final
    Definition Classes
    Any
  7. def clone (): AnyRef

    Attributes
    protected[lang]
    Definition Classes
    AnyRef
    Annotations
    @throws()
  8. implicit val defaultInterruptor : Interruptor

    Implicit Interruptor value defining a default interruption strategy for the failAfter method.

    Implicit Interruptor value defining a default interruption strategy for the failAfter method.

    To change the default Interruptor configuration, override or hide this val with another implicit Interruptor.

    Attributes
    implicit
  9. def eq (arg0: AnyRef): Boolean

    Attributes
    final
    Definition Classes
    AnyRef
  10. def equals (arg0: Any): Boolean

    Definition Classes
    AnyRef → Any
  11. def failAfter [T] (timeout: Span)(fun: ⇒ T)(implicit interruptor: Interruptor): T

    Executes the passed function, enforcing the passed time limit by attempting to interrupt the function if the time limit is exceeded, and throwing TestFailedDueToTimeoutException if the time limit has been exceeded after the function completes.

    Executes the passed function, enforcing the passed time limit by attempting to interrupt the function if the time limit is exceeded, and throwing TestFailedDueToTimeoutException if the time limit has been exceeded after the function completes.

    If the function completes before the timeout expires:

    • If the function returns normally, this method will return normally.
    • If the function completes abruptly with an exception, this method will complete abruptly with that same exception.

    If the function completes after the timeout expires:

    • If the function returns normally, this method will complete abruptly with a TestFailedDueToTimeoutException.
    • If the function completes abruptly with an exception, this method will complete abruptly with a TestFailedDueToTimeoutException that includes the exception thrown by the function as its cause.

    If the interrupted status of the main test thread (the thread that invoked failAfter) was not invoked when failAfter was invoked, but is set after the operation times out, it is reset by this method before it completes abruptly with a TestFailedDueToTimeoutException. The interrupted status will be set by ThreadInterruptor, the default Interruptor implementation.

    timeout

    the maximimum amount of time allowed for the passed operation

    fun

    the operation on which to enforce the passed timeout

    interruptor

    a strategy for interrupting the passed operation

  12. def finalize (): Unit

    Attributes
    protected[lang]
    Definition Classes
    AnyRef
    Annotations
    @throws()
  13. def getClass (): java.lang.Class[_]

    Attributes
    final
    Definition Classes
    AnyRef
  14. def hashCode (): Int

    Definition Classes
    AnyRef → Any
  15. def isInstanceOf [T0] : Boolean

    Attributes
    final
    Definition Classes
    Any
  16. def ne (arg0: AnyRef): Boolean

    Attributes
    final
    Definition Classes
    AnyRef
  17. def notify (): Unit

    Attributes
    final
    Definition Classes
    AnyRef
  18. def notifyAll (): Unit

    Attributes
    final
    Definition Classes
    AnyRef
  19. def synchronized [T0] (arg0: ⇒ T0): T0

    Attributes
    final
    Definition Classes
    AnyRef
  20. def toString (): String

    Definition Classes
    AnyRef → Any
  21. def wait (): Unit

    Attributes
    final
    Definition Classes
    AnyRef
    Annotations
    @throws()
  22. def wait (arg0: Long, arg1: Int): Unit

    Attributes
    final
    Definition Classes
    AnyRef
    Annotations
    @throws()
  23. def wait (arg0: Long): Unit

    Attributes
    final
    Definition Classes
    AnyRef
    Annotations
    @throws()

Inherited from AnyRef

Inherited from Any