teardown-0.0.0.1: test/TestSuite.hs
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Protolude
import Test.Tasty (TestTree, defaultMainWithIngredients, testGroup)
import Test.Tasty.HUnit
import Test.Tasty.Ingredients.Rerun (rerunningTests)
import Test.Tasty.Runners (consoleTestReporter, listingTests)
import Control.Teardown
import Data.IORef (atomicModifyIORef, newIORef, readIORef)
main :: IO ()
main =
defaultMainWithIngredients
[ rerunningTests [listingTests, consoleTestReporter] ]
tests
tests :: TestTree
tests =
testGroup "teardown"
[
testCase "idempotent execution of teardown action" $ do
callCountRef <- newIORef (0 :: Int)
teardownAction <- newTeardown "test cleanup" $
atomicModifyIORef callCountRef (\a -> (succ a, ()))
replicateM_ 10 (teardown teardownAction)
callCount <- readIORef callCountRef
assertEqual "teardown action got called more than once"
1 callCount
, testCase "failing teardown action does not stop execution" $ do
teardownAction <- newTeardown "failing teardown" $
panic "failing teardown"
result <- teardown teardownAction
replicateM_ 9 (teardown teardownAction)
assertBool "result should report an error"
(didTeardownFail result)
, testCase "thread safe idempotent execution of teardown action" $ do
callCountRef <- newIORef (0 :: Int)
teardownAction <- newTeardown "test cleanup" $
atomicModifyIORef callCountRef (\a -> (succ a, ()))
asyncList <-
replicateM 10 (async
-- each async executes teardown 3 times
$ replicateM_ 3
$ void $ teardown teardownAction)
mapM_ wait asyncList
callCount <- readIORef callCountRef
assertEqual "teardown action must not be called more than once"
1 callCount
, testCase "concatenated teardown actions keep idempotent guarantees" $ do
callCountRefs <- replicateM 10 $ newIORef (0 :: Int)
teardownActions <- forM callCountRefs $ \callCountRef ->
newTeardown "test cleanup"
(atomicModifyIORef callCountRef (\a -> (succ a, ())))
let
teardownAction =
concatTeardown "bigger system" teardownActions
replicateM_ 10 (teardown teardownAction)
countRefs <- mapM readIORef callCountRefs
assertEqual "teardown action must not be called more than once"
(replicate 10 1)
countRefs
, testCase "concatenated teardown actions return correct count" $ do
teardownActions <-
replicateM 10 (newTeardown "test cleanup" (return ()))
let
teardownAction =
concatTeardown "bigger system" teardownActions
toredownResult <- teardown teardownAction
replicateM_ 9 (teardown teardownAction)
assertEqual "teardown action must not be called more than once"
10 (toredownCount toredownResult)
, testCase "concatenated failed teardown actions return correct count" $ do
failedTeardownActions <-
replicateM 5 (newTeardown "test cleanup with failures" (panic "nope"))
teardownActions <-
replicateM 5 (newTeardown "test cleanup" (return ()))
let
teardownAction =
concatTeardown "bigger system"
(failedTeardownActions <> teardownActions)
toredownResult <- teardown teardownAction
replicateM_ 9 (teardown teardownAction)
assertEqual "teardown action count must be correct"
10 (toredownCount toredownResult)
assertEqual "failed teardown action must be correct"
5 (failedToredownCount toredownResult)
, testCase "dynamic teardown behave similar to vanilla teardown" $ do
callCountRef <- newIORef (0 :: Int)
failedTeardownActions <-
replicateM 5 (newTeardown "test cleanup with failures" (panic "nope"))
teardownActions <-
replicateM 5 (newTeardown "test cleanup"
(atomicModifyIORef callCountRef (\a -> (succ a, ()))))
let
teardownAction =
newDynTeardown "bigger system" $
mapM teardown (failedTeardownActions <> teardownActions)
teardownResult <- teardown teardownAction
replicateM_ 9 (teardown teardownAction)
teardownSuccessCount <- readIORef callCountRef
assertEqual "teardown action count must be correct"
10 (toredownCount teardownResult)
assertEqual "teardown action must be idempotent"
5 teardownSuccessCount
]