Created
February 29, 2020 19:09
-
-
Save jonaskoelker/b4a1d00a3da97c6d56e7b3d8fee02716 to your computer and use it in GitHub Desktop.
The Bounded Queue ScalaCheck Commands object I want to write
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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