Class/Object

monix.execution.schedulers

TestScheduler

Related Docs: object TestScheduler | package schedulers

Permalink

final class TestScheduler extends ReferenceScheduler with BatchingScheduler

Scheduler and a provider of cats.effect.Timer instances, that can simulate async boundaries and time passage, useful for testing purposes.

Usage for simulating an ExecutionContext:

implicit val ec = TestScheduler()

ec.execute(new Runnable { def run() = println("task1") })

ex.execute(new Runnable {
  def run() = {
    println("outer")

    ec.execute(new Runnable {
      def run() = println("inner")
    })
  }
})

// Nothing executes until `tick` gets called
ec.tick()

// Testing the resulting state
assert(ec.state.tasks.isEmpty)
assert(ec.state.lastReportedError == null)

TestScheduler can also simulate the passage of time:

val ctx = TestScheduler()
val f = Task(1 + 1).delayExecution(10.seconds).runAsync

// This only triggers immediate execution, so nothing happens yet
ctx.tick()
assert(f.value == None)

// Simulating the passage of 5 seconds, nothing happens yet
ctx.tick(5.seconds)
assert(f.value == None)

// Simulating another 5 seconds, now we're done!
assert(f.value == Some(Success(2)))

We are also able to build a cats.effect.Timer from any Scheduler and for any data type:

val ctx = TestScheduler()

val timer: Timer[IO] = ctx.timer[IO]

We can now simulate time passage for cats.effect.IO as well:

val io = timer.sleep(10.seconds) *> IO(1 + 1)
val f = io.unsafeToFuture()

// This invariant holds true, because our IO is async
assert(f.value == None)

// Not yet completed, because this does not simulate time passing:
ctx.tick()
assert(f.value == None)

// Simulating time passing:
ctx.tick(10.seconds)
assert(f.value == Some(Success(2))

Simulating time makes this pretty useful for testing race conditions:

val timeoutError = new TimeoutException
val timeout = Task.raiseError[Int](timeoutError)
  .delayExecution(10.seconds)

val pair = (Task.never, timeout).parMapN(_ + _)

// Not yet
ctx.tick()
assert(f.value == None)

// Not yet
ctx.tick(5.seconds)
assert(f.value == None)

// Good to go:
ctx.tick(5.seconds)
assert(f.value == Some(Failure(timeoutError)))
Linear Supertypes
Ordering
  1. Alphabetic
  2. By Inheritance
Inherited
  1. TestScheduler
  2. BatchingScheduler
  3. ReferenceScheduler
  4. Scheduler
  5. Executor
  6. UncaughtExceptionReporter
  7. Serializable
  8. Serializable
  9. ExecutionContext
  10. AnyRef
  11. Any
  1. Hide All
  2. Show All
Visibility
  1. Public
  2. All

Value Members

  1. final def !=(arg0: Any): Boolean

    Permalink
    Definition Classes
    AnyRef → Any
  2. final def ##(): Int

    Permalink
    Definition Classes
    AnyRef → Any
  3. final def ==(arg0: Any): Boolean

    Permalink
    Definition Classes
    AnyRef → Any
  4. final def asInstanceOf[T0]: T0

    Permalink
    Definition Classes
    Any
  5. def clockMonotonic(unit: TimeUnit): Long

    Permalink

    Returns a monotonic clock measurement, if supported by the underlying platform.

    Returns a monotonic clock measurement, if supported by the underlying platform.

    This is the pure equivalent of Java's System.nanoTime, or of CLOCK_MONOTONIC from Linux's clock_gettime().

    timer.clockMonotonic(NANOSECONDS)

    The returned value can have nanoseconds resolution and represents the number of time units elapsed since some fixed but arbitrary origin time. Usually this is the Unix epoch, but that's not a guarantee, as due to the limits of Long this will overflow in the future (263 is about 292 years in nanoseconds) and the implementation reserves the right to change the origin.

    The return value should not be considered related to wall-clock time, the primary use-case being to take time measurements and compute differences between such values, for example in order to measure the time it took to execute a task.

    As a matter of implementation detail, Monix's Scheduler implementations use System.nanoTime and the JVM will use CLOCK_MONOTONIC when available, instead of CLOCK_REALTIME (see clock_gettime() on Linux) and it is up to the underlying platform to implement it correctly.

    And be warned, there are platforms that don't have a correct implementation of CLOCK_MONOTONIC. For example at the moment of writing there is no standard way for such a clock on top of JavaScript and the situation isn't so clear cut for the JVM either, see:

    The JVM tries to do the right thing and at worst the resolution and behavior will be that of System.currentTimeMillis.

    The recommendation is to use this monotonic clock when doing measurements of execution time, or if you value monotonically increasing values more than a correspondence to wall-time, or otherwise prefer clockRealTime.

    Definition Classes
    TestSchedulerReferenceSchedulerScheduler
  6. def clockRealTime(unit: TimeUnit): Long

    Permalink

    Returns the current time, as a Unix timestamp (number of time units since the Unix epoch).

    Returns the current time, as a Unix timestamp (number of time units since the Unix epoch).

    This is the equivalent of Java's System.currentTimeMillis, or of CLOCK_REALTIME from Linux's clock_gettime().

    The provided TimeUnit determines the time unit of the output, its precision, but not necessarily its resolution, which is implementation dependent. For example this will return the number of milliseconds since the epoch:

    import scala.concurrent.duration.MILLISECONDS
    
    scheduler.clockRealTime(MILLISECONDS)

    N.B. the resolution is limited by the underlying implementation and by the underlying CPU and OS. If the implementation uses System.currentTimeMillis, then it can't have a better resolution than 1 millisecond, plus depending on underlying runtime (e.g. Node.js) it might return multiples of 10 milliseconds or more.

    See clockMonotonic, for fetching a monotonic value that may be better suited for doing time measurements.

    Definition Classes
    TestSchedulerReferenceSchedulerScheduler
  7. def clone(): AnyRef

    Permalink
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  8. final def eq(arg0: AnyRef): Boolean

    Permalink
    Definition Classes
    AnyRef
  9. def equals(arg0: Any): Boolean

    Permalink
    Definition Classes
    AnyRef → Any
  10. final def execute(runnable: Runnable): Unit

    Permalink

    Schedules the given command for execution at some time in the future.

    Schedules the given command for execution at some time in the future.

    The command may execute in a new thread, in a pooled thread, in the calling thread, basically at the discretion of the Scheduler implementation.

    Definition Classes
    BatchingSchedulerScheduler → Executor → ExecutionContext
  11. def executeAsync(r: Runnable): Unit

    Permalink
    Attributes
    protected
    Definition Classes
    TestSchedulerBatchingScheduler
    Annotations
    @tailrec()
  12. val executionModel: ExecutionModel

    Permalink

    The ExecutionModel is a specification of how run-loops and producers should behave in regards to executing tasks either synchronously or asynchronously.

    The ExecutionModel is a specification of how run-loops and producers should behave in regards to executing tasks either synchronously or asynchronously.

    Definition Classes
    TestSchedulerScheduler
  13. val features: Features

    Permalink

    Exposes a set of flags that describes the Scheduler's features.

    Exposes a set of flags that describes the Scheduler's features.

    Definition Classes
    TestSchedulerScheduler
  14. def finalize(): Unit

    Permalink
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    @throws( classOf[java.lang.Throwable] )
  15. final def getClass(): Class[_]

    Permalink
    Definition Classes
    AnyRef → Any
  16. def hashCode(): Int

    Permalink
    Definition Classes
    AnyRef → Any
  17. final def isInstanceOf[T0]: Boolean

    Permalink
    Definition Classes
    Any
  18. final def ne(arg0: AnyRef): Boolean

    Permalink
    Definition Classes
    AnyRef
  19. final def notify(): Unit

    Permalink
    Definition Classes
    AnyRef
  20. final def notifyAll(): Unit

    Permalink
    Definition Classes
    AnyRef
  21. def prepare(): ExecutionContext

    Permalink
    Definition Classes
    ExecutionContext
  22. def reportFailure(t: Throwable): Unit

    Permalink

    Reports that an asynchronous computation failed.

    Reports that an asynchronous computation failed.

    Definition Classes
    TestSchedulerSchedulerUncaughtExceptionReporter → ExecutionContext
    Annotations
    @tailrec()
  23. def scheduleAtFixedRate(initialDelay: Long, period: Long, unit: TimeUnit, r: Runnable): Cancelable

    Permalink

    Schedules a periodic task that becomes enabled first after the given initial delay, and subsequently with the given period.

    Schedules a periodic task that becomes enabled first after the given initial delay, and subsequently with the given period. Executions will commence after initialDelay then initialDelay + period, then initialDelay + 2 * period and so on.

    If any execution of the task encounters an exception, subsequent executions are suppressed. Otherwise, the task will only terminate via cancellation or termination of the scheduler. If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute.

    For example the following schedules a message to be printed to standard output approximately every 10 seconds with an initial delay of 5 seconds:

    val task = scheduler.scheduleAtFixedRate(5, 10, TimeUnit.SECONDS, new Runnable {
      def run() = print("Repeated message")
    })
    
    // later if you change your mind ...
    task.cancel()
    initialDelay

    is the time to wait until the first execution happens

    period

    is the time to wait between 2 successive executions of the task

    unit

    is the time unit used for the initialDelay and the period parameters

    r

    is the callback to be executed

    returns

    a cancelable that can be used to cancel the execution of this repeated task at any time.

    Definition Classes
    ReferenceSchedulerScheduler
  24. def scheduleOnce(initialDelay: Long, unit: TimeUnit, r: Runnable): Cancelable

    Permalink

    Schedules a task to run in the future, after initialDelay.

    Schedules a task to run in the future, after initialDelay.

    For example the following schedules a message to be printed to standard output after 5 minutes:

    val task = scheduler.scheduleOnce(5, TimeUnit.MINUTES, new Runnable {
      def run() = print("Hello, world!")
    })
    
    // later if you change your mind ...
    task.cancel()
    initialDelay

    is the time to wait until the execution happens

    unit

    is the time unit used for initialDelay

    r

    is the callback to be executed

    returns

    a Cancelable that can be used to cancel the created task before execution.

    Definition Classes
    TestSchedulerScheduler
    Annotations
    @tailrec()
  25. def scheduleWithFixedDelay(initialDelay: Long, delay: Long, unit: TimeUnit, r: Runnable): Cancelable

    Permalink

    Schedules for execution a periodic task that is first executed after the given initial delay and subsequently with the given delay between the termination of one execution and the commencement of the next.

    Schedules for execution a periodic task that is first executed after the given initial delay and subsequently with the given delay between the termination of one execution and the commencement of the next.

    For example the following schedules a message to be printed to standard output every 10 seconds with an initial delay of 5 seconds:

    val task = s.scheduleWithFixedDelay(5, 10, TimeUnit.SECONDS, new Runnable {
      def run() = print("Repeated message")
    })
    
    // later if you change your mind ...
    task.cancel()
    initialDelay

    is the time to wait until the first execution happens

    delay

    is the time to wait between 2 successive executions of the task

    unit

    is the time unit used for the initialDelay and the delay parameters

    r

    is the callback to be executed

    returns

    a cancelable that can be used to cancel the execution of this repeated task at any time.

    Definition Classes
    ReferenceSchedulerScheduler
  26. def state: State

    Permalink

    Returns the internal state of the TestScheduler, useful for testing that certain execution conditions have been met.

  27. final def synchronized[T0](arg0: ⇒ T0): T0

    Permalink
    Definition Classes
    AnyRef
  28. def tick(time: FiniteDuration = Duration.Zero, maxImmediateTasks: Option[Int] = None): Unit

    Permalink

    Triggers execution by going through the queue of scheduled tasks and executing them all, until no tasks remain in the queue to execute.

    Triggers execution by going through the queue of scheduled tasks and executing them all, until no tasks remain in the queue to execute.

    Order of execution isn't guaranteed, the queued Runnables are being shuffled in order to simulate the needed non-determinism that happens with multi-threading.

    implicit val ec = TestScheduler()
    
    val f = Future(1 + 1).map(_ + 1)
    // Execution is momentarily suspended in TestContext
    assert(f.value == None)
    
    // Simulating async execution:
    ec.tick()
    assert(f.value, Some(Success(2)))

    The optional parameter can be used for simulating time:

    implicit val ec = TestScheduler()
    
    val f = Task.sleep(10.seconds).map(_ => 10).runAsync
    
    // Not yet completed, because this does not simulate time passing:
    ctx.tick()
    assert(f.value == None)
    
    // Simulating time passing:
    ctx.tick(10.seconds)
    assert(f.value == Some(Success(10))
    time

    is an optional parameter for simulating time passing

    maxImmediateTasks

    is an optional parameter that specifies a maximum number of immediate tasks to execute one after another; setting this parameter can prevent non-termination

  29. def tickOne(): Boolean

    Permalink

    Executes just one tick, one task, from the internal queue, useful for testing that some runnable will definitely be executed next.

    Executes just one tick, one task, from the internal queue, useful for testing that some runnable will definitely be executed next.

    Returns a boolean indicating that tasks were available and that the head of the queue has been executed, so normally you have this equivalence:

    while (ec.tickOne()) {}
    // ... is equivalent with:
    ec.tick()

    Note that task extraction has a random factor, the behavior being like tick, in order to simulate non-determinism. So you can't rely on some ordering of execution if multiple tasks are waiting execution.

    returns

    true if a task was available in the internal queue, and was executed, or false otherwise

    Annotations
    @tailrec()
  30. def toString(): String

    Permalink
    Definition Classes
    AnyRef → Any
  31. final def wait(): Unit

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

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

    Permalink
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  34. def withExecutionModel(em: ExecutionModel): TestScheduler

    Permalink

    Given a function that will receive the underlying ExecutionModel, returns a new Scheduler reference, based on the source, that exposes the transformed ExecutionModel when queried by means of the executionModel property.

    Given a function that will receive the underlying ExecutionModel, returns a new Scheduler reference, based on the source, that exposes the transformed ExecutionModel when queried by means of the executionModel property.

    This method enables reusing global scheduler references in a local scope, but with a slightly modified execution model to inject.

    The contract of this method (things you can rely on):

    1. the source Scheduler must not be modified in any way
    2. the implementation should wrap the source efficiently, such that the result mirrors the source Scheduler in every way except for the execution model

    Sample:

    import monix.execution.Scheduler.global
    
    implicit val scheduler = {
      val em = global.executionModel
      global.withExecutionModel(em.withAutoCancelableLoops(true))
    }
    Definition Classes
    TestSchedulerReferenceSchedulerScheduler
  35. def withUncaughtExceptionReporter(r: UncaughtExceptionReporter): Scheduler

    Permalink

    Returns a new Scheduler that piggybacks on this, but uses the given exception reporter for reporting uncaught errors.

    Returns a new Scheduler that piggybacks on this, but uses the given exception reporter for reporting uncaught errors.

    Sample:

    import monix.execution.Scheduler.global
    import monix.execution.UncaughtExceptionReporter
    
    implicit val scheduler = {
      val r = UncaughtExceptionReporter { e =>
        e.printStackTrace()
      }
      global.withUncaughtExceptionReporter(r)
    }
    Definition Classes
    ReferenceSchedulerScheduler

Inherited from BatchingScheduler

Inherited from ReferenceScheduler

Inherited from Scheduler

Inherited from Executor

Inherited from UncaughtExceptionReporter

Inherited from Serializable

Inherited from Serializable

Inherited from ExecutionContext

Inherited from AnyRef

Inherited from Any

Ungrouped