cauldron-0.9.0.0: test/appTests.hs
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE NoFieldSelectors #-}
-- | The example in the executable, as a test.
module Main (main) where
import Cauldron
import Test.Tasty
import Test.Tasty.HUnit
data A = A deriving (Show)
data B = B deriving (Show)
data C = C deriving (Show)
data D = D deriving (Show)
data E = E deriving (Show)
data F = F deriving (Show)
data G = G deriving (Show)
data H = H deriving (Show)
data I = I deriving (Show)
data J = J deriving (Show)
data K = K deriving (Show)
data L = L deriving (Show)
data M = M deriving (Show)
data N = N deriving (Show)
data O = O deriving (Show)
data P = P deriving (Show)
data Q = Q deriving (Show)
data R = R deriving (Show)
data S = S deriving (Show)
data T = T deriving (Show)
data U = U deriving (Show)
data V = V deriving (Show)
data W = W deriving (Show)
data X = X deriving (Show)
data Y = Y deriving (Show)
data Z = Z deriving (Show)
newtype Inspector = Inspector {_inspect :: IO [String]}
deriving newtype (Semigroup, Monoid)
newtype Initializer = Initializer {_runInitializer :: IO ()}
deriving newtype (Semigroup, Monoid)
makeA :: A
makeA = A
makeB :: (Inspector, B)
makeB = (Inspector (pure ["B stuff"]), B)
makeC :: C
makeC = C
makeD :: D
makeD = D
makeE :: A -> E
makeE = \_ -> E
makeF :: B -> C -> (Inspector, F)
makeF = \_ _ -> (Inspector (pure ["F stuff"]), F)
makeG :: E -> F -> G -> G
makeG _ _ (_ :: G) = G
makeGDeco1 :: A -> G -> G
makeGDeco1 _ g = g
makeH :: A -> D -> G -> (Initializer, Inspector, H)
makeH _ _ _ = (Initializer (putStrLn "H init"), Inspector (pure ["H stuff"]), H)
makeZ :: Inspector -> D -> H -> Z
makeZ _ _ _ = Z
makeZDeco1 :: B -> E -> Z -> Z
makeZDeco1 _ _ z = z
makeZDeco2 :: F -> Z -> (Initializer, Z)
makeZDeco2 = \_ z -> (Initializer (putStrLn "Z deco init"), z)
coolWiring :: Fire IO -> Either CookingError (IO Result)
coolWiring fire = do
cook fire cauldron
cauldron :: Cauldron IO
cauldron :: Cauldron IO =
mconcat
[ singleton $ val $ pure makeA,
singleton $ val $ pure makeB,
singleton $ val $ wire makeC,
singleton $ val $ wire makeD,
singleton $ val $ wire makeE,
-- The type app in val checks the specificity, see val definition.
recipe @F $ val @F $ wire makeF,
recipe @G
Recipe
{ bare = val $ wire makeG,
decos =
fromDecoList
[ val $ wire makeGDeco1
]
},
recipe @H $ val $ wire makeH,
recipe @Z
Recipe
{ bare = val $ wire makeZ,
decos =
fromDecoList
[ val $ wire makeZDeco1,
val $ wire makeZDeco2
]
},
recipe @Result $ val $ wire Result
]
data Result = Result Initializer Inspector Z
tests :: TestTree
tests =
testGroup
"All"
[ testCase "example" do
case coolWiring allowSelfDeps of
Left badBeans -> assertFailure do show badBeans
Right _ -> pure ()
pure (),
testCase "dep cycles forbidden" do
case coolWiring forbidDepCycles of
Left (DependencyCycleError _) -> pure ()
Left _ -> assertFailure do "wrong kind of error detected"
Right _ -> assertFailure do "self dependency not detected"
pure ()
]
main :: IO ()
main = defaultMain tests