{-# LANGUAGE RecordWildCards, GeneralizedNewtypeDeriving #-}
module Test.Util(
Test, withTests,
passed, failed, progress,
addIdeas, getIdeas,
BuiltinSummary, BuiltinEx(..), addBuiltin, getBuiltins,
) where
import Idea
import Control.Monad
import Control.Monad.Trans.Reader
import Control.Monad.IO.Class
import Data.IORef
import Data.List.Extra
import Data.Map (Map)
import qualified Data.Map.Strict as Map
type BuiltinSummary = Map (String, Severity, Bool) BuiltinEx
data BuiltinEx = BuiltinEx
{ builtinInp :: !String
, builtinFrom :: !String
, builtinTo :: !(Maybe String)
}
data S = S
{failures :: !Int
,total :: !Int
,ideas :: [[Idea]]
,builtinHints :: BuiltinSummary
}
newtype Test a = Test (ReaderT (IORef S) IO a)
deriving (Functor, Applicative, Monad, MonadIO)
withTests :: Test a -> IO (Int, a)
withTests (Test act) = do
ref <- newIORef $ S 0 0 [] Map.empty
res <- runReaderT act ref
S{..} <- readIORef ref
putStrLn ""
putStrLn $ if failures == 0
then "Tests passed (" ++ show total ++ ")"
else "Tests failed (" ++ show failures ++ " of " ++ show total ++ ")"
pure (failures, res)
addIdeas :: [Idea] -> Test ()
addIdeas xs = do
ref <- Test ask
liftIO $ modifyIORef' ref $ \s -> s{ideas = xs : ideas s}
getIdeas :: Test [Idea]
getIdeas = do
ref <- Test ask
liftIO $ concat . reverse . ideas <$> readIORef ref
addBuiltin :: String -> Idea -> Test ()
addBuiltin inp idea@Idea{..} = unless ("Parse error" `isPrefixOf` ideaHint) $ do
ref <- Test ask
liftIO $ modifyIORef' ref $ \s ->
let k = (ideaHint, ideaSeverity, notNull ideaRefactoring)
v = BuiltinEx inp ideaFrom ideaTo
in s{builtinHints = Map.insertWith (curry snd) k v (builtinHints s)}
getBuiltins :: Test BuiltinSummary
getBuiltins = do
ref <- Test ask
liftIO $ builtinHints <$> readIORef ref
progress :: Test ()
progress = liftIO $ putChar '.'
passed :: Test ()
passed = do
ref <- Test ask
liftIO $ modifyIORef' ref $ \s -> s{total=total s+1}
failed :: [String] -> Test ()
failed xs = do
unless (null xs) $ liftIO $ putStrLn $ unlines $ "" : xs
ref <- Test ask
liftIO $ modifyIORef' ref $ \s -> s{total=total s+1, failures=failures s+1}