unliftio-0.2.8.0: test/UnliftIO/MemoizeSpec.hs
{-# LANGUAGE DeriveDataTypeable #-}
module UnliftIO.MemoizeSpec (spec) where
import Control.Concurrent (threadDelay)
import Control.Monad (replicateM_)
import Test.Hspec
import Test.Hspec.QuickCheck
import UnliftIO
import Data.Typeable
data Dummy = Dummy
deriving (Show, Typeable)
instance Exception Dummy
spec :: Spec
spec = do
let basics maker = do
prop "sanity" $ \i -> do
x <- maker $ return (i :: Int)
runMemoized x `shouldReturn` i
prop "runs once" $ \i -> do
count <- newIORef (0 :: Int)
x <- maker $ do
modifyIORef' count (+ 1)
return (i :: Int)
replicateM_ 10 $ runMemoized x `shouldReturn` i
readIORef count `shouldReturn` 1
it "runs once with exception" $ do
count <- newIORef (0 :: Int)
x <- maker $ do
modifyIORef' count (+ 1)
throwIO Dummy
replicateM_ 10 $ runMemoized x `shouldThrow` (\Dummy -> True)
readIORef count `shouldReturn` 1
describe "memoizeRef" $ basics memoizeRef
describe "memoizeMVar" $ do
basics memoizeMVar
prop "runs once in multiple threads" $ \i -> do
count <- newIORef (0 :: Int)
x <- memoizeMVar $ do
threadDelay 10000
atomicModifyIORef' count $ \cnt -> (cnt + 1, ())
return (i :: Int)
replicateConcurrently_ 10 $ runMemoized x `shouldReturn` i
readIORef count `shouldReturn` 1