{-# LANGUAGE LambdaCase #-}
module Test.Tasty.Lua.Core
( runTastyFile
, ResultTree (..)
, Outcome (..)
, UnnamedTree (..)
)
where
import Control.Monad (void)
import Data.ByteString (ByteString)
import Foreign.Lua (Lua, Peekable, StackIndex)
import Test.Tasty.Lua.Module (pushModule)
import qualified Data.Text as Text
import qualified Data.Text.Encoding as Text.Encoding
import qualified Foreign.Lua as Lua
import qualified Test.Tasty as Tasty
runTastyFile :: FilePath -> Lua (Either String [ResultTree])
runTastyFile fp = do
Lua.openlibs
Lua.requirehs "tasty" (void pushModule)
res <- Lua.dofile fp
if res /= Lua.OK
then Left . toString <$> Lua.tostring' Lua.stackTop
else Lua.try (Lua.peekList Lua.stackTop) >>= \case
Left (Lua.Exception e) -> return (Left e)
Right trees -> return (Right trees)
toString :: ByteString -> String
toString = Text.unpack . Text.Encoding.decodeUtf8
data ResultTree = ResultTree Tasty.TestName UnnamedTree
instance Peekable ResultTree where
peek = peekResultTree
peekResultTree :: StackIndex -> Lua ResultTree
peekResultTree idx = do
name <- Lua.getfield idx "name" *> Lua.popValue
result <- Lua.getfield idx "result" *> Lua.popValue
return $ ResultTree name result
data UnnamedTree
= SingleTest Outcome
| TestGroup [ResultTree]
instance Peekable UnnamedTree where
peek = peekUnnamedTree
peekUnnamedTree :: StackIndex -> Lua UnnamedTree
peekUnnamedTree idx = do
ty <- Lua.ltype idx
case ty of
Lua.TypeTable -> TestGroup <$> Lua.peekList idx
_ -> SingleTest <$> Lua.peek idx
data Outcome = Success | Failure String
instance Peekable Outcome where
peek = peekOutcome
peekOutcome :: StackIndex -> Lua Outcome
peekOutcome idx = do
ty <- Lua.ltype idx
case ty of
Lua.TypeString -> Failure <$> Lua.peek idx
Lua.TypeBoolean -> do
b <- Lua.peek idx
return $ if b then Success else Failure "???"
_ -> do
s <- toString <$> Lua.tostring' idx
Lua.throwException ("not a test result: " ++ s)