packages feed

hamtmap-0.2: tests/tests.hs

import Test.QuickCheck
import Test.QuickCheck.Batch
import Data.Hashable
import Data.HamtMap as HM
import Data.Int
import Data.List (foldl', sort)
import Data.Maybe (isNothing)
import Prelude as P

ldelete :: (Eq k) => k -> [(k, v)] -> [(k, v)]
ldelete _ [] = []
ldelete k ((k', v'):xs) | k' == k   = ldelete k xs
                        | otherwise = (k', v') : ldelete k xs

lset :: (Eq k) => k -> v -> [(k, v)] -> [(k, v)]
lset k v [] = []
lset k v ((k', v'):xs) | k' == k   = (k, v) : lset k v xs
                       | otherwise = (k', v') : lset k v xs

prop_insert :: (Eq k, Hashable k, Eq v) => (k -> Int32) -> k -> v -> [(k, v)] -> Bool
prop_insert hashFn k v lm =
    let hm  = fromList hashFn lm
        hm' = insert k v hm
        in    member k hm'
           && not (notMember k hm')
           && HM.lookup k hm' == Just v
           && hm' ! k == v
           && (if member k hm
                  then toList hm == lset k (hm ! k) (toList hm')
                  else toList hm == ldelete k (toList hm')
                  )

prop_delete :: (Eq k, Hashable k, Eq v) => (k -> Int32) -> k -> [(k, v)] -> Bool
prop_delete hashFn k lm =
    let hm  = fromList hashFn lm
        hm' = delete k hm
        in    not (member k hm')
           && notMember k hm'
           && isNothing (HM.lookup k hm')
           && (if member k hm
                  then toList hm' == ldelete k (toList hm)
                  else toList hm' == toList hm
                  )

prop_fromList :: (Eq k, Hashable k, Ord k, Eq v, Ord v) => (k -> Int32) -> [(k, v)] -> Bool
prop_fromList hashFn lm =
    let hm = fromList hashFn lm
        hm' = foldl' (\hm (k,v) -> insert k v hm) (empty hashFn) lm
        in sort (toList hm) == sort (toList hm')

prop_toList :: (Eq k, Hashable k, Ord k, Eq v, Ord v) => (k -> Int32) -> [(k, v)] -> Bool
prop_toList hashFn lm =
    let hm = fromList hashFn lm
        lm' = toList hm
        ks = keys hm
        ks' = P.map fst lm'
        els = elems hm
        els' = P.map snd lm'
        els'' = P.map (\k -> hm ! k) ks
        in    ks == ks'
           && els == els'
           && els == els''


options = TestOptions
      { no_of_tests         = 200
      , length_of_tests     = 2 -- seconds
      , debug_tests         = False }

main = runTests "tests" options
    [ run (prop_insert fromIntegral :: Int -> Int -> [(Int,Int)] -> Bool)
    , run (prop_insert (fromIntegral.(`mod` 2)) :: Int -> Int -> [(Int,Int)] -> Bool)
    , run (prop_delete fromIntegral :: Int -> [(Int, Int)] -> Bool)
    , run (prop_delete (fromIntegral.(`mod` 2)) :: Int -> [(Int,Int)] -> Bool)
    , run (prop_fromList fromIntegral :: [(Int, Int)] -> Bool)
    , run (prop_fromList (fromIntegral.(`mod` 2)) :: [(Int, Int)] -> Bool)
    , run (prop_toList fromIntegral :: [(Int, Int)] -> Bool)
    , run (prop_toList (fromIntegral.(`mod` 2)) :: [(Int, Int)] -> Bool)
    ]