packages feed

creatur-5.3.2: test/ALife/Creatur/UtilQC.hs

------------------------------------------------------------------------
-- |
-- Module      :  ALife.Creatur.UtilQC
-- Copyright   :  (c) Amy de Buitléir 2012-2014
-- License     :  BSD-style
-- Maintainer  :  amy@nualeargais.ie
-- Stability   :  experimental
-- Portability :  portable
--
-- QuickCheck tests.
--
------------------------------------------------------------------------
module ALife.Creatur.UtilQC
  (
    test
  ) where

import ALife.Creatur.Util (cropRect, cropSquare, isqrt, replaceElement, 
  safeReplaceElement, shuffle)
import Control.Monad.Random (evalRand, mkStdGen)
import Data.Ix (range)
import Data.List (sort)
import Test.Framework as TF (Test, testGroup)
import Test.Framework.Providers.QuickCheck2 (testProperty)
import Test.QuickCheck (Property, property)

-- prop_constrain_obeys_bounds :: (Int, Int) -> Int -> Property
-- prop_constrain_obeys_bounds (a, b) x = property $ a <= x' && x' <= b
--  where x' = constrain (a, b) x

-- prop_constrain_works :: (Int, Int) -> Int -> Property
-- prop_constrain_works (a, b) x = property $ x' == x || x <= a || b <= x || b < a
--  where x' = constrain (a, b) x

prop_cropRect_returns_correct_size ::
  (Int, Int) -> (Int, Int) -> String -> Int -> Property
prop_cropRect_returns_correct_size (a,b) (c,d) xs k =
    property $ length xs' == expectedSize || length xs < minimalOriginalSize
  where expectedSize = length is'
        is = range ((0,0),(lastRow,lastCol))
        is' = filter wanted is
        wanted (i,j) = a <= i && i <= c && b <= j && j <= d
        lastRow = if k == 0 then -1 else (length xs `div` k) - 1 + delta
        lastCol = constrain (-1,length xs - 1) (k - 1)
        delta = if length xs `mod` k == 0 then 0 else 1 --add partial row
        xs' = cropRect (a, b) (c, d) xs k
        minimalOriginalSize = c*k + d + 1
          -- the last row of the original matrix must have at least
          -- d+1 elements

-- Warning: If b < a, returns either a or x
constrain :: Ord a => (a, a) -> a -> a
constrain (a,b) x | x < a     = a
                  | x > b     = b
                  | otherwise = x

prop_cropSquare_returns_correct_size :: Int -> String -> Property
prop_cropSquare_returns_correct_size n xs =
    property $ length xs' == expectedSize
  where expectedRows = min n ((isqrt . length) xs)
        expectedSize = if n < 0 then 0 else expectedRows*expectedRows
        xs' = cropSquare n xs

prop_replaceElement_changes_the_right_element :: String -> Int -> Char -> Property
prop_replaceElement_changes_the_right_element cs i c =
  property
    $
      if 0 <= i && i < length cs
        then replaceElement cs i c !! i == c
        else replaceElement cs i c == cs

prop_safeReplaceElement_doesnt_change_length :: String -> Int -> Char -> Property
prop_safeReplaceElement_doesnt_change_length cs i c =
  property $ length cs == length (safeReplaceElement cs i c)

prop_safeReplaceElement_changes_the_right_element ::
  String -> Int -> Char -> Property
prop_safeReplaceElement_changes_the_right_element cs i c =
  property
    $
      if 0 <= i && i < length cs
        then cs' !! i == c
        else cs' == cs
  where cs' = safeReplaceElement cs i c

prop_shuffle_doesnt_change_elements :: String -> Int -> Property
prop_shuffle_doesnt_change_elements xs k = property $ sort xs == sort xs'
  where xs' = evalRand (shuffle xs) (mkStdGen k)

test :: Test
test = testGroup "QuickCheck ALife.Creatur.UtilQC"
  [
--    testProperty "prop_constrain_obeys_bounds"
--      prop_constrain_obeys_bounds,
--    testProperty "prop_constrain_works"
--      prop_constrain_works,
    testProperty "prop_safeReplaceElement_changes_the_right_element"
      prop_safeReplaceElement_changes_the_right_element,
    testProperty "prop_safeReplaceElement_doesnt_change_length"
      prop_safeReplaceElement_doesnt_change_length,
    testProperty "prop_cropRect_returns_correct_size"
      prop_cropRect_returns_correct_size,
    testProperty "prop_cropSquare_returns_correct_size"
      prop_cropSquare_returns_correct_size,
    testProperty "prop_replaceElement_changes_the_right_element"
      prop_replaceElement_changes_the_right_element,
    testProperty "prop_shuffle_doesnt_change_elements"
      prop_shuffle_doesnt_change_elements
  ]