ginger2-2.1.0.0: test/Language/Ginger/TestUtils.hs
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
module Language.Ginger.TestUtils
where
import Control.Monad.Identity
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import Data.Maybe (listToMaybe)
import Data.Text (Text)
import qualified Data.Text as Text
import qualified Data.Map.Strict as Map
import Test.Tasty.QuickCheck
import System.Random (mkStdGen)
import Language.Ginger.Interpret
import Language.Ginger.Value
import Language.Ginger.AST
newtype ArbitraryText = ArbitraryText { unArbitraryText :: Text }
deriving (Eq, Ord)
instance Show ArbitraryText where
show (ArbitraryText t) = show t
instance Arbitrary ArbitraryText where
arbitrary = ArbitraryText . Text.pack <$> listOf arbitrary
instance Monad m => ToValue ArbitraryText m where
toValue (ArbitraryText t) = toValue t
newtype NonEmptyText = NonEmptyText Text
deriving (Eq, Ord)
instance Show NonEmptyText where
show (NonEmptyText t) = show t
instance Arbitrary NonEmptyText where
arbitrary = NonEmptyText . Text.pack <$> listOf1 arbitrary
instance Monad m => ToValue NonEmptyText m where
toValue (NonEmptyText t) = toValue t
newtype ArbitraryByteString = ArbitraryByteString ByteString
deriving (Eq, Ord)
instance Show ArbitraryByteString where
show (ArbitraryByteString t) = show t
instance Arbitrary ArbitraryByteString where
arbitrary = ArbitraryByteString . BS.pack <$> listOf arbitrary
instance Monad m => ToValue ArbitraryByteString m where
toValue (ArbitraryByteString t) = toValue t
newtype PositiveInt i = PositiveInt i
deriving (Eq, Ord)
instance Show i => Show (PositiveInt i) where
show (PositiveInt t) = show t
instance (Arbitrary i, Integral i) => Arbitrary (PositiveInt i) where
arbitrary = do
s <- getSize
PositiveInt . fromInteger <$> chooseInteger (1, fromIntegral $ max 1 s)
shrink (PositiveInt i) = map PositiveInt . filter (> 0) $ shrink i
instance (Monad m, ToValue i m) => ToValue (PositiveInt i) m where
toValue (PositiveInt t) = toValue t
safeAt :: Int -> [a] -> Maybe a
safeAt n = listToMaybe . drop n
justNonzero :: (Eq a, Num a) => a -> Maybe a
justNonzero 0 = Nothing
justNonzero n = Just n
justPositive :: (Eq a, Ord a, Num a) => a -> Maybe a
justPositive n | n > 0 = Just n
justPositive _ = Nothing
leftPRE :: RuntimeError -> Either PrettyRuntimeError a
leftPRE = Left . PrettyRuntimeError
mapLeft :: (a -> b) -> Either a c -> Either b c
mapLeft f (Left x) = Left (f x)
mapLeft _ (Right x) = Right x
mapRight :: (b -> c) -> Either a b -> Either a c
mapRight _ (Left x) = Left x
mapRight f (Right x) = Right (f x)
newtype PrettyRuntimeError = PrettyRuntimeError RuntimeError
deriving (Eq)
instance Show PrettyRuntimeError where
show (PrettyRuntimeError (TemplateParseError _ err)) = Text.unpack err
show (PrettyRuntimeError e) = show e
runGingerIdentity :: Int -> GingerT Identity a -> a
runGingerIdentity rngSeed action =
either (error . show) id $ runGingerIdentityEither rngSeed action
runGingerIdentityEither :: Int -> GingerT Identity a -> Either PrettyRuntimeError a
runGingerIdentityEither rngSeed action =
mapLeft (PrettyRuntimeError . unPositionedError) $
runIdentity (runGingerT action defContext defEnv (mkStdGen rngSeed))
runGingerIdentityWithLoader :: TemplateLoader Identity
-> Int
-> GingerT Identity a
-> a
runGingerIdentityWithLoader loader rngSeed action =
either (error . show) id $ runGingerIdentityEitherWithLoader loader rngSeed action
runGingerIdentityEitherWithLoader :: TemplateLoader Identity
-> Int
-> GingerT Identity a
-> Either PrettyRuntimeError a
runGingerIdentityEitherWithLoader loader rngSeed action =
mapLeft (PrettyRuntimeError . unPositionedError) $
runIdentity
(runGingerT
action
defContext { contextLoadTemplateFile = loader }
defEnv
(mkStdGen rngSeed))
mockLoader :: [(Text, Text)] -> TemplateLoader Identity
mockLoader entries name =
pure $ Map.lookup name tpls
where
tpls = Map.fromList entries
unPositionedS :: Statement -> Statement
unPositionedS = traverseS go unPositionedE
where
go (PositionedS _ s) = unPositionedS s
go s = s
unPositionedE :: Expr -> Expr
unPositionedE = traverseE go unPositionedS
where
go (PositionedE _ e) = unPositionedE e
go e = e
unPositionedError :: RuntimeError -> RuntimeError
unPositionedError (PositionedError _ e) = unPositionedError e
unPositionedError e = e