Skip to content

Instantly share code, notes, and snippets.

@jonaskoelker
Created February 29, 2020 19:09
Show Gist options
  • Save jonaskoelker/b4a1d00a3da97c6d56e7b3d8fee02716 to your computer and use it in GitHub Desktop.
Save jonaskoelker/b4a1d00a3da97c6d56e7b3d8fee02716 to your computer and use it in GitHub Desktop.
The Bounded Queue ScalaCheck Commands object I want to write
import org.scalacheck.{Arbitrary, Gen, Prop, Properties, Shrink}
import org.scalacheck.commands.Commands
import org.scalacheck.Prop.{forAll, propBoolean}
import org.scalacheck.Test.Parameters.default
import scala.util.{Try, Success}
class BoundedQueueSpec extends Properties("BoundedQueue Spec") {
property("Bounded Queue is a bounded queue") = BoundedQueueSpec.property()
}
object BoundedQueueSpec extends Commands {
type Element = Byte
type Sut = BoundedQueue[Element]
case class State(capacity: Int, elements: Seq[Element])
case object Capacity extends Command {
type Result = Int
def run(sut: Sut): Result = sut.capacity
def nextState(state: State): State = state
def preCondition(state: State): Boolean = true
def postCondition(state: State, result: Try[Result]): Prop =
result == Success(state.capacity)
}
case object Size extends Command {
type Result = Int
def run(sut: Sut): Result = sut.size
def nextState(state: State): State = state
def preCondition(state: State): Boolean = true
def postCondition(state: State, result: Try[Result]): Prop =
result == Success(state.elements.length)
}
case class Enqueue(element: Element) extends UnitCommand {
def run(sut: Sut): Unit =
sut.enqueue(element)
def nextState(state: State): State =
State(state.capacity, state.elements ++ List(element))
def preCondition(state: State): Boolean =
state.elements.length < state.capacity
def postCondition(state: State, success: Boolean): Prop =
success
}
case object Dequeue extends Command {
type Result = Element
def run(sut: Sut): Result =
sut.dequeue()
def nextState(state: State): State =
State(state.capacity, state.elements.tail)
def preCondition(state: State): Boolean =
state.elements.nonEmpty
def postCondition(state: State, result: Try[Result]): Prop =
result == Success(state.elements.head)
}
def genInitialState: Gen[State] =
for {
n <- Gen.choose(10, 20)
} yield State(n, List())
def genCommand(state: State): Gen[Command] =
Gen.oneOf(
Gen.const(Capacity),
Gen.const(Size),
Gen.const(Dequeue),
Arbitrary.arbitrary[Element].flatMap(Enqueue(_))
)
def newSut(state: State): Sut =
new BoundedQueue(state.capacity)
def initialPreCondition(state: State): Boolean =
state.capacity >= 0 && state.elements.isEmpty
override def shrinkState: Shrink[State] = Shrink {
case State(capacity, elements) => for {
(cap, elems) <- implicitly[Shrink[(Int, Seq[Element])]].shrink((capacity, elements))
} yield State(cap, elems take cap)
}
override def shrinkCommand: Shrink[Command] = Shrink {
case Enqueue(n) => Stream(Capacity, Size, Dequeue) ++
implicitly[Shrink[Element]].shrink(n).map(Enqueue(_))
case Dequeue => Stream(Capacity, Size)
case Size => Stream(Capacity)
case Capacity => Stream.empty
}
def canCreateNewSut(
newState: State,
initSuts: Traversable[State],
runningSuts: Traversable[Sut]
): Boolean =
true
def destroySut(sut: Sut): Unit =
()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment