critbit-0.0.0.0: tests/Properties.hs
{-# LANGUAGE CPP, GeneralizedNewtypeDeriving #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Properties
where
import Control.Applicative ((<$>))
import Data.ByteString (ByteString)
import Data.CritBit.Map.Lazy (CritBitKey, CritBit)
import Data.Text (Text)
import Data.Word (Word8)
import Test.Framework (Test, testGroup)
import Test.Framework.Providers.QuickCheck2 (testProperty)
import Test.QuickCheck (Arbitrary(..), Args(..), quickCheckWith, stdArgs)
import Test.QuickCheck.Property (Testable)
import qualified Data.ByteString as BB
import qualified Data.ByteString.Char8 as B
import qualified Data.CritBit.Map.Lazy as C
import qualified Data.Map as Map
import qualified Data.Text as T
instance Arbitrary ByteString where
arbitrary = BB.pack <$> arbitrary
shrink = map B.pack . shrink . B.unpack
instance Arbitrary Text where
arbitrary = T.pack <$> arbitrary
shrink = map T.pack . shrink . T.unpack
type V = Word8
newtype KV a = KV { fromKV :: [(a, V)] }
deriving (Show, Eq, Ord)
instance Arbitrary a => Arbitrary (KV a) where
arbitrary = (KV . flip zip [0..]) <$> arbitrary
shrink = map (KV . flip zip [0..]) . shrink . map fst . fromKV
instance (CritBitKey k, Arbitrary k, Arbitrary v) =>
Arbitrary (CritBit k v) where
arbitrary = C.fromList <$> arbitrary
shrink = map C.fromList . shrink . C.toList
newtype CB k = CB (CritBit k V)
deriving (Show, Eq, Arbitrary)
t_lookup_present :: (CritBitKey k) => k -> k -> V -> CB k -> Bool
t_lookup_present _ k v (CB m) = C.lookup k (C.insert k v m) == Just v
t_lookup_missing :: (CritBitKey k) => k -> k -> CB k -> Bool
t_lookup_missing _ k (CB m) = C.lookup k (C.delete k m) == Nothing
#if MIN_VERSION_containers(0,5,0)
t_lookupGT :: (Ord k, CritBitKey k) => k -> k -> KV k -> Bool
t_lookupGT _ k (KV kvs) =
C.lookupGT k (C.fromList kvs) == Map.lookupGT k (Map.fromList kvs)
#endif
t_fromList_toList :: (CritBitKey k, Ord k) => k -> KV k -> Bool
t_fromList_toList _ (KV kvs) =
Map.toList (Map.fromList kvs) == C.toList (C.fromList kvs)
t_fromList_size :: (CritBitKey k, Ord k) => k -> KV k -> Bool
t_fromList_size _ (KV kvs) =
Map.size (Map.fromList kvs) == C.size (C.fromList kvs)
t_delete_present :: (CritBitKey k, Ord k) => k -> KV k -> k -> V -> Bool
t_delete_present _ (KV kvs) k v =
C.toList (C.delete k c) == Map.toList (Map.delete k m)
where
c = C.insert k v $ C.fromList kvs
m = Map.insert k v $ Map.fromList kvs
t_unionL :: (CritBitKey k, Ord k) => k -> KV k -> KV k -> Bool
t_unionL _ (KV kv0) (KV kv1) =
Map.toList (Map.fromList kv0 `Map.union` Map.fromList kv1) ==
C.toList (C.fromList kv0 `C.unionL` C.fromList kv1)
t_foldl :: (CritBitKey k) => k -> CritBit k V -> Bool
t_foldl _ m = C.foldl (+) 0 m == C.foldr (+) 0 m
t_foldlWithKey :: (CritBitKey k, Ord k) => k -> KV k -> Bool
t_foldlWithKey _ (KV kvs) =
C.foldlWithKey f ([], 0) (C.fromList kvs) ==
Map.foldlWithKey f ([], 0) (Map.fromList kvs)
where
f (l,s) k v = (k:l,s+v)
t_foldl' :: (CritBitKey k) => k -> CritBit k V -> Bool
t_foldl' _ m = C.foldl' (+) 0 m == C.foldl (+) 0 m
t_foldlWithKey' :: (CritBitKey k, Ord k) => k -> KV k -> Bool
t_foldlWithKey' _ (KV kvs) =
C.foldlWithKey' f ([], 0) (C.fromList kvs) ==
Map.foldlWithKey' f ([], 0) (Map.fromList kvs)
where
f (l,s) k v = (k:l,s+v)
t_keys :: (CritBitKey k, Ord k) => k -> KV k -> Bool
t_keys _ (KV kvs) = C.keys (C.fromList kvs) == Map.keys (Map.fromList kvs)
propertiesFor :: (Arbitrary k, CritBitKey k, Ord k, Show k) => k -> [Test]
propertiesFor t = [
testProperty "t_fromList_toList" $ t_fromList_toList t
, testProperty "t_fromList_size" $ t_fromList_size t
, testProperty "t_lookup_present" $ t_lookup_present t
, testProperty "t_lookup_missing" $ t_lookup_missing t
#if MIN_VERSION_containers(0,5,0)
, testProperty "t_lookupGT" $ t_lookupGT t
#endif
, testProperty "t_delete_present" $ t_delete_present t
, testProperty "t_unionL" $ t_unionL t
, testProperty "t_foldl" $ t_foldl t
, testProperty "t_foldlWithKey" $ t_foldlWithKey t
, testProperty "t_foldl'" $ t_foldl' t
, testProperty "t_foldlWithKey'" $ t_foldlWithKey' t
, testProperty "t_keys" $ t_keys t
]
properties :: [Test]
properties = [
testGroup "text" $ propertiesFor T.empty
, testGroup "bytestring" $ propertiesFor B.empty
]
-- Handy functions for fiddling with from ghci.
blist :: [ByteString] -> CritBit ByteString Word8
blist = C.fromList . flip zip [0..]
tlist :: [Text] -> CritBit Text Word8
tlist = C.fromList . flip zip [0..]
mlist :: [ByteString] -> Map.Map ByteString Word8
mlist = Map.fromList . flip zip [0..]
qc :: Testable prop => Int -> prop -> IO ()
qc n = quickCheckWith stdArgs { maxSuccess = n }