{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}
module Main where
import Data.Cache.LRU
import Control.Concurrent.STM
import Distribution.TestSuite as TestSuite
import Test.Hspec as Hspec
import Test.Hspec.Core.Runner
import Test.QuickCheck
import Test.QuickCheck.Monadic as QC
import SDL.Data.Cache
main :: IO ()
main = hspec functionTest
newtype CacheInteger = CacheInteger { fromCacheInteger :: Integer }
deriving (Eq,Ord,Num,Arbitrary,Show)
instance Cacheable CacheInteger where
releaseResource _ = return ()
data StatefulBool a = StatefulBool { fromStatefulBool :: TVar Bool
, sbVal :: a
}
instance Cacheable (StatefulBool a) where
releaseResource b = atomically $ writeTVar (fromStatefulBool b) True
isReleased :: StatefulBool a -> IO Bool
isReleased b = atomically $ readTVar (fromStatefulBool b)
newStatefulBool :: a -> IO (StatefulBool a)
newStatefulBool x = StatefulBool <$> (atomically $ newTVar False) <*> pure x
functionTest :: Spec
functionTest =
describe "Data.Cache.LRU" $ do
it "drops the least recently added item" $ do
property $ \ (Positive (cacheSize :: Int)) ->
snd $
foldl
(\ (lru,ok) n ->
if not ok
then (lru, False)
else case insertInforming n n lru of
(lru', Nothing) -> (lru', True)
(lru', Just (m,_)) ->
if m == n - cacheSize
then (lru', True)
else (lru', False)
)
(newLRU (Just (fromIntegral cacheSize)), True)
[1..cacheSize * 2]
describe "SDL.Data.Cache.Cache" $ do
it "produces the same result as without the Cache" $
property $ \ (n :: CacheInteger) ->
monadicIO $ assert =<< QC.run
(do let calc x = return (2*x)
res <- calc n
cache <- newCache 1
resCached <- throughCache cache n (calc n)
return (res == resCached)
)
it "releases all resources when emptying the cache" $
property $ \ (Positive (cacheSize :: Int)) (Positive (differentElements :: Int)) ->
monadicIO $ assert =<< QC.run
(do cache <- newCache cacheSize
bs <- mapM
(\n -> throughCache cache n (newStatefulBool n))
[1..differentElements]
emptyCache cache
and <$> mapM isReleased bs
)