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

hedgehog.state.Command.scala Maven / Gradle / Ivy

There is a newer version: 0.11.0
Show newest version
package hedgehog.state

import hedgehog.core._

/**
 * The specification for the expected behaviour of an `Action`.
 */
trait Command[S, I, O] extends CommandIO[S] {

  type Input = I
  type Output = O

  /**
   * Return a list of _all_ `Var` instances referenced by `Input`
   *
   * Failure to do this correctly will result in missing variable errors during shrinking.
   */
  def vars(i: Input): List[Var[_]] =
    Nil

  /**
   * A generator which provides random arguments for a command.
   * If the command cannot be executed in the current state, it should return `None`.
   */
  def gen(s: S): Option[GenT[Input]]

  /**
   * Executes a command using the arguments generated by [[gen]].
   */
  def execute(env: Environment, s: Input): Either[String, Output]

  /**
   * A pre-condition for a command that must be verified before the command can be executed.
   * This is mainly used during shrinking to ensure that it is still OK to run a command
   * despite the fact that some previously executed commands may have been removed from the sequence.
   */
  def require(s: S, i: Input): Boolean =
    true

  /**
   * Updates the model state, given the input and output of the command.
   */
  def update(s0: S, i: Input, o: Var[Output]): S

  /**
   * A post-condition for a command that must be verified for the command to be considered a success.
   */
  def ensure(env: Environment, before: S, after: S, i: Input, o: Output): Result

  /**
   * Render the input for displaying in test output.
   *
   * The default is to use `toString`, but optionally can support being overridden.
   */
  def renderInput(i: Input): String =
    String.valueOf(i)

  final override def command: Command[S, Input, Output] =
    this
}

/**
 * Capture the `Input` and `Output` variables from `Command` existentially.
 *
 * FIXME If we can make the rest of the code play nicely with path-dependent types then we can remove this.
 */
trait CommandIO[S] {

  type Input
  type Output

  def command: Command[S, Input, Output]
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy