{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Main (main) where
import Test.QuickCheck (Gen, Arbitrary(..), choose, shrinkIntegral)
import Test.Framework (defaultMain, testGroup, Test)
import Test.Framework.Providers.QuickCheck2 (testProperty)
import Test.Framework.Providers.HUnit (testCase)
import Test.HUnit (Assertion,(@?=))
import Data.Coerce
import Data.Word
import Data.Function (on)
import Data.List (groupBy)
import Control.Monad
import Control.Monad.ST
import qualified Data.List as List
import qualified Data.Set as Set
import qualified Data.Map.Strict as Map
import Debug.Trace
import qualified Data.Heap.Mutable.ModelD as HeapD
main :: IO ()
main = defaultMain tests
tests :: [Test]
tests =
[ testGroup "Heaps"
[ testProperty "Model D Push No Crash" multipush
, testProperty "Model D Push Pop" heapPushPop
, testProperty "Model D List" heapMatchesList
]
]
testElements :: Int
testElements = 15
newtype Min = Min { getMin :: Word32 }
deriving (Show,Read,Eq,Ord)
instance Arbitrary Min where
arbitrary = fmap Min (choose (0,20))
shrink (Min a) = fmap Min $ filter (>= 0) $ shrinkIntegral a
instance Monoid Min where
mempty = Min 0
mappend (Min a) (Min b) = Min (min a b)
newtype MyElement = MyElement { getMyElement :: Int }
deriving (Show,Read,Eq,Ord)
instance Arbitrary MyElement where
arbitrary = fmap MyElement (choose (0,fromIntegral testElements - 1))
shrink (MyElement a) = fmap MyElement $ filter (>= 0) $ shrinkIntegral a -- fmap MyElement (enumFromTo 0 (a - 1))
multipush :: [(Min,MyElement)] -> Bool
multipush xs = runST $ do
h <- trace "Running Test" (HeapD.new testElements)
HeapD.pushList (coerce xs :: [(Min,Int)]) h
return True
heapPushPop :: [(Min,MyElement)] -> Bool
heapPushPop xs =
let res = runST $ do
h <- HeapD.new testElements
forM xs $ \(c,MyElement i) -> do
HeapD.push c i h
HeapD.pop h
in sequence res == coerce (Just xs)
heapMatchesList :: [(Min,MyElement)] -> Bool
heapMatchesList xs' =
let xs = coerce xs' :: [(Min,Int)]
xsSet = fmap (\(p,e) -> (e,p)) xs
ys = Map.fromListWith mappend xsSet
listRes = Map.toList $ Map.fromListWith Set.union $ map (\(e,p) -> (p,Set.singleton e)) (Map.toList ys)
heapRes = runST $ do
h <- HeapD.new testElements
HeapD.pushList xs h
HeapD.popAll h
heapResSet = map (\pairs@((p,_) : _) -> (p,Set.fromList $ map snd pairs))
$ groupBy (on (==) fst) heapRes
in heapResSet == listRes