packages feed

freer-simple-1.0.0.0: tests/Tests/Loop.hs

module Tests.Loop (tests) where

import Control.Concurrent (forkIO, killThread)
import Control.Concurrent.QSemN (newQSemN, signalQSemN, waitQSemN)
import Control.Monad (forever)
import Data.Function (fix)

import Test.Tasty (TestTree, localOption, mkTimeout, testGroup)
import Test.Tasty.HUnit (testCase)

import Control.Monad.Freer (Eff, Member, runM, send)

tests :: TestTree
tests = localOption timeout $ testGroup "Loop tests"
    [ testCase "fix loop" $ testLoop fixLoop
    , testCase "tail loop" $ testLoop tailLoop
    , testCase "forever loop" $ testLoop foreverLoop
    ]
  where
    timeout = mkTimeout 1000000

testLoop :: (IO () -> Eff '[IO] ()) -> IO ()
testLoop loop = do
  s <- newQSemN 0
  t <- forkIO . runM . loop $ signalQSemN s 1
  waitQSemN s 5
  killThread t

fixLoop :: Member IO r => IO () -> Eff r ()
fixLoop action = fix $ \fxLoop -> do
  send action
  fxLoop

tailLoop :: Member IO r => IO () -> Eff r ()
tailLoop action = let loop = send action *> loop in loop

foreverLoop :: Member IO r => IO () -> Eff r ()
foreverLoop action = forever $ send action