{-# LANGUAGE TemplateHaskell, TypeFamilies, GADTs, ExistentialQuantification, CPP #-} -- module Tests where import Control.Monad import qualified Data.TrieMap as T import qualified Data.Map as M import Test.QuickCheck import Prelude hiding (null, lookup) type Key = [String] type Val = [String] main = quickCheck (verify M.empty T.empty) instance Arbitrary Op where arbitrary = oneof [ liftM Op (liftM2 Insert arbitrary arbitrary), return (Op Map), return (Op ToList), return (Op Size), liftM (Op . Lookup) arbitrary, liftM (Op . Delete) arbitrary, return (Op MinView), return (Op MaxView), return (Op MapMaybe)] shrink (Op (Insert k v)) = [Op (Insert k' v') | k' <- shrink k, v' <- shrink v] shrink (Op (Lookup k)) = map (Op . Lookup) (shrink k) shrink (Op (Delete k)) = map (Op . Delete) (shrink k) shrink _ = [] data Op = forall r . Op (Operation r) instance Show Op where show (Op (Insert k v)) = "Insert " ++ show k ++ " " ++ show v show (Op (Lookup k)) = "Lookup " ++ show k show (Op (Delete k)) = "Delete " ++ show k show (Op Map) = "Map" show (Op Size) = "Size" show (Op ToList) = "ToList" show (Op MinView) = "MinView" show (Op MaxView) = "MaxView" show (Op MapMaybe) = "MapMaybe" data Operation r where Insert :: Key -> Val -> Operation () Map :: Operation () ToList :: Operation [(Key, Val)] Size :: Operation Int Lookup :: Key -> Operation (Maybe Val) Delete :: Key -> Operation () MinView :: Operation (Maybe (Key, Val)) MaxView :: Operation (Maybe (Key, Val)) MapMaybe :: Operation () operateMap :: M.Map Key Val -> Operation r -> (r, M.Map Key Val) operateMap m (Insert k v) = ((), M.insert k v m) operateMap m (Lookup k) = (M.lookup k m, m) operateMap m Map = ((), M.mapWithKey (\ k a -> k ++ a) m) operateMap m ToList = (M.assocs m, m) operateMap m Size = (M.size m, m) operateMap m (Delete k) = ((), M.delete k m) operateMap m MinView = case M.minViewWithKey m of Nothing -> (Nothing, m) Just ((k, v), m') -> (Just (k, v), m') operateMap m MaxView = case M.maxViewWithKey m of Nothing -> (Nothing, m) Just (kv, m') -> (Just kv, m') operateMap m MapMaybe = ((), M.mapMaybeWithKey f m) where f ("":xs) ("":ys) = Just (xs ++ ys) f _ _ = Nothing operateTMap :: T.TMap Key Val -> Operation r -> (r, T.TMap Key Val) operateTMap m (Insert k v) = ((), T.insert k v m) operateTMap m (Lookup k) = (T.lookup k m, m) operateTMap m Map = ((), T.mapWithKey (\ k a -> k ++ a) m) operateTMap m ToList = (T.assocs m, m) operateTMap m Size = (T.size m, m) operateTMap m (Delete k) = ((), T.delete k m) operateTMap m MinView = case T.minViewWithKey m of Nothing -> (Nothing, m) Just ((k, v), m') -> (Just (k, v), m') operateTMap m MaxView = case T.maxViewWithKey m of Nothing -> (Nothing, m) Just (kv, m') -> (Just kv, m') operateTMap m MapMaybe = ((), T.mapMaybeWithKey f m) where f ("":xs) ("":ys) = Just (xs ++ ys) f _ _ = Nothing #define VERIFYOP(operation) verifyOp op@operation{} m tm = \ case (operateMap m op, operateTMap tm op) of \ {((r1, m'), (r2, tm')) -> guard (r1 == r2 && M.assocs m' == T.assocs tm') >> return (m', tm');} verifyOp :: Operation r -> M.Map Key Val -> T.TMap Key Val -> Maybe (M.Map Key Val, T.TMap Key Val) VERIFYOP(Insert) VERIFYOP(Lookup) VERIFYOP(Map) VERIFYOP(Size) VERIFYOP(ToList) VERIFYOP(Delete) VERIFYOP(MinView) VERIFYOP(MaxView) VERIFYOP(MapMaybe) verify :: M.Map Key Val -> T.TMap Key Val -> [Op] -> Bool verify m tm (Op op:ops) = case verifyOp op m tm of Nothing -> False Just (m', tm') -> verify m' tm' ops verify _ _ [] = True