2014-08-06 18:41:59 +00:00
|
|
|
module MonadSpec where
|
|
|
|
|
|
|
|
import Test.Hspec
|
2014-08-12 16:11:32 +00:00
|
|
|
import TestUtils
|
2014-08-06 18:41:59 +00:00
|
|
|
import Control.Monad.Error.Class
|
2016-01-04 18:05:15 +00:00
|
|
|
import Control.Concurrent
|
|
|
|
import Control.Exception
|
2014-08-06 18:41:59 +00:00
|
|
|
|
|
|
|
spec :: Spec
|
|
|
|
spec = do
|
|
|
|
describe "When using GhcModT in a do block" $
|
|
|
|
it "a pattern match failure causes a call to `fail` on ErrorT in the monad stack" $ do
|
2015-03-04 20:48:21 +00:00
|
|
|
(a, _h)
|
2015-09-14 08:11:33 +00:00
|
|
|
<- runGmOutDef $ runGhcModT defaultOptions $
|
2014-08-06 18:41:59 +00:00
|
|
|
do
|
2014-08-20 03:14:27 +00:00
|
|
|
Just _ <- return Nothing
|
2014-08-06 18:41:59 +00:00
|
|
|
return "hello"
|
|
|
|
`catchError` (const $ fail "oh noes")
|
|
|
|
a `shouldBe` (Left $ GMEString "oh noes")
|
2016-01-04 18:05:15 +00:00
|
|
|
|
|
|
|
describe "runGhcModT" $
|
|
|
|
it "throws an exception when run in multiple threads" $ do
|
2016-01-19 19:51:11 +00:00
|
|
|
|
|
|
|
mv_ex :: MVar (Either SomeException ())
|
2016-01-04 18:05:15 +00:00
|
|
|
<- newEmptyMVar
|
2016-01-19 19:51:11 +00:00
|
|
|
mv_startup_barrier :: MVar () <- newEmptyMVar
|
|
|
|
|
|
|
|
_t1 <- forkOS $ do
|
|
|
|
putMVar mv_startup_barrier ()
|
|
|
|
-- wait (inside GhcModT) for t2 to receive the exception
|
|
|
|
_ <- runD $ liftIO $ readMVar mv_ex
|
|
|
|
return ()
|
|
|
|
|
|
|
|
_t2 <- forkOS $ do
|
|
|
|
readMVar mv_startup_barrier -- wait for t1 to start up
|
|
|
|
res <- try $ runD $ return ()
|
|
|
|
res' <- evaluate res
|
|
|
|
putMVar mv_ex res'
|
2016-01-04 18:05:15 +00:00
|
|
|
|
2016-01-19 19:51:11 +00:00
|
|
|
ex <- takeMVar mv_ex
|
2016-01-04 18:05:15 +00:00
|
|
|
|
2016-01-19 19:51:11 +00:00
|
|
|
isLeft ex `shouldBe` True
|
2016-01-04 18:05:15 +00:00
|
|
|
|
|
|
|
isLeft :: Either a b -> Bool
|
|
|
|
isLeft (Right _) = False
|
|
|
|
isLeft (Left _) = True
|