gamgee-1.1.0: test/Gamgee/Test/Effects.hs
module Gamgee.Test.Effects
( runOutputPure
, runListSecretInput
, runCryptoRandom
, runByteStoreST
) where
import Control.Monad.ST (ST)
import qualified Crypto.Random as CR
import qualified Crypto.Random.Types as CRT
import Data.STRef (STRef)
import qualified Data.STRef as STRef
import qualified Gamgee.Effects as Eff
import Polysemy (Lift, Member, Sem)
import qualified Polysemy as P
import qualified Polysemy.Output as P
import qualified Polysemy.State as P
import Relude
----------------------------------------------------------------------------------------------------
-- Interpret Output by accumulating it in a list
----------------------------------------------------------------------------------------------------
runOutputPure :: Sem (P.Output o : r) a -> Sem r ([o], a)
runOutputPure = P.runFoldMapOutput one
----------------------------------------------------------------------------------------------------
-- Interpret SecretInput by reading from a list
----------------------------------------------------------------------------------------------------
runListSecretInput :: [i] -> Sem (Eff.SecretInput i : r) a -> Sem r a
runListSecretInput is = fmap snd . P.runState is . P.reinterpret
(\case
Eff.SecretInput _ -> do
s <- P.gets uncons
whenJust s (P.put . snd)
maybe
(error "Ran out of input in SecretInput")
return
(fst <$> s)
)
----------------------------------------------------------------------------------------------------
-- Interpret CryptoRandom with a DRG
----------------------------------------------------------------------------------------------------
runCryptoRandom :: CR.DRG gen => gen -> Sem (Eff.CryptoRandom : r) a -> Sem r a
runCryptoRandom gen = P.interpret $ \case
Eff.RandomBytes count -> return (fst $ CR.withDRG gen (CRT.getRandomBytes count))
----------------------------------------------------------------------------------------------------
-- Interpret ByteStore using the ST monad
----------------------------------------------------------------------------------------------------
runByteStoreST :: Member (Lift (ST s)) r => STRef s (Maybe LByteString) -> Sem (Eff.ByteStore : r) a -> Sem r a
runByteStoreST ref = P.interpret $ \case
Eff.ReadByteStore -> P.sendM $ STRef.readSTRef ref
Eff.WriteByteStore bytes -> P.sendM $ STRef.writeSTRef ref (Just bytes)