packages feed

holmes-0.3.0.1: test/Test/Data/Propagator.hs

{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE ViewPatterns #-}
module Test.Data.Propagator where

import qualified Control.Monad.Cell.Class as Cell
import Data.Holmes
import qualified Data.Propagator as Prop
import Hedgehog
import qualified Hedgehog.Gen as Gen
import qualified Hedgehog.Range as Range
import Data.List (nub)
import Prelude hiding (read)
import Test.Control.Monad.Cell.Class (Lestrade, read, scotlandYardSays)

hprop_eqR_reflexivity :: Property
hprop_eqR_reflexivity = property do
  x <- forAll (Gen.int (Range.linear 0 10))

  let program :: Lestrade h ()
      program = Prop.down (Prop.lift x .== Prop.lift x)
            >>= \o -> Cell.write o (Exactly True)

  if scotlandYardSays program == Nothing
    then failure
    else success

hprop_eqR_negation :: Property
hprop_eqR_negation = property do
  x <- forAll (Gen.int (Range.linear 0 10))
  y <- forAll (Gen.int (Range.linear 0 10))

  let this :: Lestrade h ()
      this = Prop.down (Prop.lift x .== Prop.lift y)
         >>= \o -> Cell.write o (Exactly True)

      that :: Lestrade h ()
      that = Prop.down (Prop.lift x ./= Prop.lift y)
         >>= \o -> Cell.write o (Exactly False)

  scotlandYardSays this === scotlandYardSays that

hprop_eqR_simple :: Property
hprop_eqR_simple = property do
  x <- forAll (Gen.int (Range.linear 0 10))
  y <- forAll (Gen.int (Range.linear 0 10))

  let program :: Lestrade h (Defined Bool)
      program = Prop.down (Prop.lift x .== Prop.lift y) >>= read

  scotlandYardSays program === Just (Exactly (x == y))

hprop_eqR_symmetry :: Property
hprop_eqR_symmetry = property do
  x <- forAll (Gen.int (Range.linear 0 10))
  y <- forAll (Gen.int (Range.linear 0 10))

  let this :: Lestrade h (Defined Bool)
      this = Prop.down (Prop.lift x .== Prop.lift y) >>= read

      that :: Lestrade h (Defined Bool)
      that = Prop.down (Prop.lift y .== Prop.lift x) >>= read

  scotlandYardSays this === scotlandYardSays that

hprop_ordR_negation :: Property
hprop_ordR_negation = property do
  x <- forAll (Gen.int (Range.linear 0 10))
  y <- forAll (Gen.int (Range.linear 0 10))

  let this :: Lestrade h (Defined Bool)
      this = Prop.down (Prop.lift x .<= Prop.lift y) >>= read

      that :: Lestrade h (Defined Bool)
      that = Prop.down (Prop.lift x .> Prop.lift y) >>= read

  scotlandYardSays this === fmap (fmap not) (scotlandYardSays that)

hprop_ordR_lteR_symmetry :: Property
hprop_ordR_lteR_symmetry = property do
  x <- forAll (Gen.int (Range.linear 0 10))
  y <- forAll (Gen.int (Range.linear 0 10))

  let this :: Lestrade h (Defined Bool)
      this = Prop.down (Prop.lift x .<= Prop.lift y) >>= read

      that :: Lestrade h (Defined Bool)
      that = Prop.down (Prop.lift y .>= Prop.lift x) >>= read

  scotlandYardSays this === scotlandYardSays that

hprop_ordR_ltR_symmetry :: Property
hprop_ordR_ltR_symmetry = property do
  x <- forAll (Gen.int (Range.linear 0 10))
  y <- forAll (Gen.int (Range.linear 0 10))

  let this :: Lestrade h (Defined Bool)
      this = Prop.down (Prop.lift x .< Prop.lift y) >>= read

      that :: Lestrade h (Defined Bool)
      that = Prop.down (Prop.lift y .> Prop.lift x) >>= read

  scotlandYardSays this === scotlandYardSays that

hprop_ordR_simple :: Property
hprop_ordR_simple = property do
  x <- forAll (Gen.int (Range.linear 0 10))
  y <- forAll (Gen.int (Range.linear 0 10))

  let x', y' :: MonadCell m => Prop m (Defined Int)
      x' = Prop.lift x
      y' = Prop.lift y

      program :: Lestrade h (Defined Bool)
      program = Prop.down (x' .<= y') >>= read

  scotlandYardSays program === Just (Exactly (x <= y))

hprop_choice_unique_choices :: Property
hprop_choice_unique_choices = property do
  n <- forAll $ Gen.int (Range.linear 0 6)
  k <- forAll $ Gen.int (Range.linear 0 n)

  let choices = Prop.choose n k

  nub choices === choices

hprop_choice_correct_number_of_choices :: Property
hprop_choice_correct_number_of_choices = property do
  n <- forAll $ Gen.int (Range.linear 0 6)
  k <- forAll $ Gen.int (Range.linear 0 n)

  let choices = Prop.choose n k
      factorial 0 = 1
      factorial m = m * factorial (pred m)

  length choices === factorial n `div` (factorial k * factorial (n-k))

hprop_exactly_simple :: Property
hprop_exactly_simple = property do
  xs <- forAll (Gen.list (Range.linear 0 10) (Gen.int (Range.linear 0 10)))
  k  <- forAll (Gen.int (Range.linear 0 (length xs)))
  x  <- forAll (Gen.int (Range.linear 0 10))

  let x' :: MonadCell m => Prop m (Defined Int)
      x' = Prop.lift x
      
      xs' :: MonadCell m => [Prop m (Defined Int)]
      xs' = map Prop.lift xs

      program :: Lestrade h (Defined Bool)
      program = Prop.down (Prop.exactly k (.== x') xs') >>= read

      expected = length (filter (==x) xs) == k

  scotlandYardSays program === Just (Exactly expected)