class Waiter extends AnyRef
Class that facilitates performing assertions outside the main test thread, such as assertions in callback methods that are invoked asynchronously.
To use Waiter
, create an instance of it in the main test thread:
val w = new Waiter // Do this in the main test thread
At some point later, call await
on the waiter:
w.await() // Call await() from the main test thread
The await
call will block until it either receives a report of a failed assertion from a different thread, at which
point it will complete abruptly with the same exception, or until it is dismissed by a different thread (or threads), at
which point it will return normally. You can optionally specify a timeout and/or a number
of dismissals to wait for. Here's an example:
import org.scalatest.time.SpanSugar._ w.await(timeout(300 millis), dismissals(2))
The default value for timeout
, provided via an implicit PatienceConfig
parameter, is 150 milliseconds. The default value for
dismissals
is 1. The await
method will block until either it is dismissed a sufficient number of times by other threads or
an assertion fails in another thread. Thus if you just want to perform assertions in just one other thread, only that thread will be
performing a dismissal, so you can use the default value of 1 for dismissals
.
Waiter
contains four overloaded forms of await
, two of which take an implicit
PatienceConfig
parameter. To change the default timeout configuration, override or hide
(if you imported the members of Waiters
companion object instead of mixing in the
trait) patienceConfig
with a new one that returns your desired configuration.
To dismiss a waiter, you just invoke dismiss
on it:
w.dismiss() // Call this from one or more other threads
You may want to put dismiss
invocations in a finally clause to ensure they happen even if an exception is thrown.
Otherwise if a dismissal is missed because of a thrown exception, an await
call will wait until it times out.
Finally, to perform an assertion in a different thread, you just apply the Waiter
to the assertion code. Here are
some examples:
w { assert(1 + 1 === 3) } // Can use assertions w { 1 + 1 should equal (3) } // Or matchers w { "hi".charAt(-1) } // Any exceptions will be forwarded to await
Here's a complete example:
import org.scalatest._ import concurrent.Waiters import scala.actors.Actor class ExampleSuite extends FunSuite with Matchers with Waiters { case class Message(text: String) class Publisher extends Actor { @volatile private var handle: Message => Unit = { (msg) => } def registerHandler(f: Message => Unit) { handle = f } def act() { var done = false while (!done) { react { case msg: Message => handle(msg) case "Exit" => done = true } } } } test("example one") { val publisher = new Publisher val message = new Message("hi") val w = new Waiter publisher.start() publisher.registerHandler { msg => w { msg should equal (message) } w.dismiss() } publisher ! message w.await() publisher ! "Exit" } }
- Source
- Waiters.scala
- Alphabetic
- By Inheritance
- Waiter
- AnyRef
- Any
- Hide All
- Show All
- Public
- All
Instance Constructors
- new Waiter()
Value Members
-
final
def
!=(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
-
final
def
##(): Int
- Definition Classes
- AnyRef → Any
-
final
def
==(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
-
def
apply(fun: ⇒ Unit): Unit
Executes the passed by-name, and if it throws an exception, forwards it to the thread that calls
await
, unless a by-name passed during a previous invocation of this method threw an exception.Executes the passed by-name, and if it throws an exception, forwards it to the thread that calls
await
, unless a by-name passed during a previous invocation of this method threw an exception.This method returns normally whether or not the passed function completes abruptly. If called multiple times, only the first invocation that yields an exception will "win" and have its exception forwarded to the thread that calls
await
. Any subsequent exceptions will be "swallowed." This method may be invoked by multiple threads concurrently, in which case it is a race to see who wins and has their exception forwarded toawait
. Theawait
call will eventually complete abruptly with the winning exception, or return normally if that instance ofWaiter
is dismissed. Any exception thrown by a by-name passed toapply
after theWaiter
has been dismissed will also be "swallowed."- fun
the by-name function to execute
-
final
def
asInstanceOf[T0]: T0
- Definition Classes
- Any
-
def
await(timeout: Timeout, dismissals: Dismissals)(implicit pos: Position): Unit
Wait for an exception to be produced by the by-name passed to
apply
, or the specified number of dismissals, timing out after the specified timeout and sleeping an interval between checks configured by an implicitPatienceConfig
.Wait for an exception to be produced by the by-name passed to
apply
, or the specified number of dismissals, timing out after the specified timeout and sleeping an interval between checks configured by an implicitPatienceConfig
.This method may only be invoked by the thread that created the
Waiter
. Each time this method completes, its internal dismissal count is reset to zero, so it can be invoked multiple times. However, onceawait
has completed abruptly with an exception produced during a call toapply
, it will continue to complete abruptly with that exception.The
timeout
parameter allows you to specify a timeout after which aTestFailedException
will be thrown with a detail message indicating theawait
call timed out. If no calls toapply
have produced an exception and an insufficient number of dismissals has been received by the time thetimeout
has expired,await
will complete abruptly withTestFailedException
.As used here, a "check" is checking to see whether an exception has been thrown by a by-name passed to
apply
or the specified number of dismissals has occurred. The "interval" is the amount of time the thread that callsawait
will sleep between "checks." -
def
await(dismissals: Dismissals)(implicit config: Waiters.PatienceConfig, pos: Position): Unit
Wait for an exception to be produced by the by-name passed to
apply
, or the specified number of dismissals, sleeping an interval between checks and timing out after a timeout, both configured by an implicitPatienceConfig
.Wait for an exception to be produced by the by-name passed to
apply
, or the specified number of dismissals, sleeping an interval between checks and timing out after a timeout, both configured by an implicitPatienceConfig
.This method may only be invoked by the thread that created the
Waiter
. Each time this method completes, its internal dismissal count is reset to zero, so it can be invoked multiple times. However, onceawait
has completed abruptly with an exception produced during a call toapply
, it will continue to complete abruptly with that exception.The
timeout
parameter allows you to specify a timeout after which aTestFailedException
will be thrown with a detail message indicating theawait
call timed out. If no calls toapply
have produced an exception and an insufficient number of dismissals has been received by the time thetimeout
has expired,await
will complete abruptly withTestFailedException
.As used here, a "check" is checking to see whether an exception has been thrown by a by-name passed to
apply
or the specified number of dismissals has occurred. The "interval" is the amount of time the thread that callsawait
will sleep between "checks."- config
the
PatienceConfig
object containing thetimeout
parameter
-
def
await(timeout: Timeout)(implicit pos: Position): Unit
Wait for an exception to be produced by the by-name passed to
apply
, or one dismissal, timing out after the specified timeout and sleeping an interval between checks configured by an implicitPatienceConfig
.Wait for an exception to be produced by the by-name passed to
apply
, or one dismissal, timing out after the specified timeout and sleeping an interval between checks configured by an implicitPatienceConfig
.This method may only be invoked by the thread that created the
Waiter
. Each time this method completes, its internal dismissal count is reset to zero, so it can be invoked multiple times. However, onceawait
has completed abruptly with an exception produced during a call toapply
, it will continue to complete abruptly with that exception.The
timeout
parameter allows you to specify a timeout after which aTestFailedException
will be thrown with a detail message indicating theawait
call timed out. If no calls toapply
have produced an exception and an insufficient number of dismissals has been received by the time thetimeout
has expired,await
will complete abruptly withTestFailedException
.As used here, a "check" is checking to see whether an exception has been thrown by a by-name passed to
apply
or a dismissal has occurred. The "interval" is the amount of time the thread that callsawait
will sleep between "checks." -
def
await()(implicit config: Waiters.PatienceConfig, pos: Position): Unit
Wait for an exception to be produced by the by-name passed to
apply
, or one dismissal, sleeping an interval between checks and timing out after a timeout, both configured by an implicitPatienceConfig
.Wait for an exception to be produced by the by-name passed to
apply
, or one dismissal, sleeping an interval between checks and timing out after a timeout, both configured by an implicitPatienceConfig
.This method may only be invoked by the thread that created the
Waiter
. Each time this method completes, its internal dismissal count is reset to zero, so it can be invoked multiple times. However, onceawait
has completed abruptly with an exception produced during a call toapply
, it will continue to complete abruptly with that exception.The
timeout
parameter allows you to specify a timeout after which aTestFailedException
will be thrown with a detail message indicating theawait
call timed out. If no calls toapply
have produced an exception and an insufficient number of dismissals has been received by the time thetimeout
has expired,await
will complete abruptly withTestFailedException
.As used here, a "check" is checking to see whether an exception has been thrown by a by-name passed to
apply
or a dismissal has occurred. The "interval" is the amount of time the thread that callsawait
will sleep between "checks."- config
the
PatienceConfig
object containing thetimeout
parameter
-
def
clone(): AnyRef
- Attributes
- protected[java.lang]
- Definition Classes
- AnyRef
- Annotations
- @throws( ... )
-
def
dismiss(): Unit
Increases the dismissal count by one.
Increases the dismissal count by one.
Once the dismissal count has reached the value passed to
await
(and no prior invocations ofapply
produced an exception),await
will return normally. -
final
def
eq(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
-
def
equals(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
-
def
finalize(): Unit
- Attributes
- protected[java.lang]
- Definition Classes
- AnyRef
- Annotations
- @throws( classOf[java.lang.Throwable] )
-
final
def
getClass(): Class[_]
- Definition Classes
- AnyRef → Any
-
def
hashCode(): Int
- Definition Classes
- AnyRef → Any
-
final
def
isInstanceOf[T0]: Boolean
- Definition Classes
- Any
-
final
def
ne(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
-
final
def
notify(): Unit
- Definition Classes
- AnyRef
-
final
def
notifyAll(): Unit
- Definition Classes
- AnyRef
-
final
def
synchronized[T0](arg0: ⇒ T0): T0
- Definition Classes
- AnyRef
-
def
toString(): String
- Definition Classes
- AnyRef → Any
-
final
def
wait(): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws( ... )
-
final
def
wait(arg0: Long, arg1: Int): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws( ... )
-
final
def
wait(arg0: Long): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws( ... )