{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedLists #-} {-# LANGUAGE ScopedTypeVariables #-} module CheckProgramMonad where import qualified Control.Exception.Safe as Safe import Test.Hspec hiding (context) import Core.Data.Structures import Core.Program.Arguments import Core.Program.Execute import Core.Program.Unlift import Core.System.Base options :: [Options] options = [ Option "all" (Just 'a') Empty "Good will to everyone" ] commands :: [Commands] commands = [ Global options , Command "go-forth" "And multiply" [] ] data Boom = Boom deriving Show instance Exception Boom boom :: Selector Boom boom = const True checkProgramMonad :: Spec checkProgramMonad = do describe "Context type" $ do it "Eq instance for None behaves" $ do None `shouldBe` None describe "Program monad" $ do it "execute with blank Context as expected" $ do context <- configure "0.1" None blank executeWith context $ do user <- getApplicationState liftIO $ do user `shouldBe` None it "execute with simple Context as expected" $ do context <- configure "0.1" None (simple options) executeWith context $ do params <- getCommandLine liftIO $ do -- this assumes that hspec isn't passing any -- command-line arguments through to us. params `shouldBe` (Parameters Nothing emptyMap emptyMap) -- not strictly necessary but sets up next spec item it "sub-programs can be run" $ do context <- configure "0.1" None blank user <- subProgram context (getApplicationState) user `shouldBe` None it "unlifting from lifted IO works" $ do execute $ do user1 <- getApplicationState withContext $ \runProgram -> do user1 `shouldBe` None user2 <- runProgram getApplicationState -- unlift! user2 `shouldBe` user1 it "thrown Exceptions can be caught" $ do context <- configure "0.1" None blank (subProgram context (throw Boom)) `shouldThrow` boom -- ok, so with that established, now try **safe-exceptions**'s -- code. Note if we move the exception handling code from -- `execute` to `subProgram` this will have to adapt. Safe.catch (subProgram context (throw Boom)) (\(_ :: Boom) -> return ()) it "MonadThrow and MonadCatch behave" $ do context <- configure "0.1" None blank subProgram context $ do Safe.catch (Safe.throw Boom) (\(_ :: Boom) -> return ())