katydid-0.4.0.1: test/Suite.hs
-- |
-- Suite parses the testsuite folder and creates test cases
module Suite (
readTestCases, tests
) where
import qualified Test.Tasty as T
import qualified Test.Tasty.HUnit as HUnit
import System.Directory (getCurrentDirectory, listDirectory, doesDirectoryExist)
import System.FilePath (FilePath, (</>), takeExtension, takeBaseName, takeDirectory)
import Text.XML.HXT.DOM.TypeDefs (XmlTree)
import Data.Katydid.Parser.Parser (Tree)
import Data.Katydid.Parser.Json (JsonTree, decodeJSON)
import Data.Katydid.Parser.Xml (decodeXML)
import Data.Katydid.Relapse.Smart (Grammar, Pattern, nullable, compile)
import qualified Data.Katydid.Relapse.Ast as Ast
import Data.Katydid.Relapse.Parser (parseGrammar)
import qualified Data.Katydid.Relapse.Derive as Derive
import qualified Data.Katydid.Relapse.MemDerive as MemDerive
import qualified Data.Katydid.Relapse.VpaDerive as VpaDerive
tests :: [TestSuiteCase] -> T.TestTree
tests testSuiteCases =
let nonRecursiveTestCases = filter (\(TestSuiteCase _ g _ _) -> not (either error id $ Ast.hasRecursion g)) testSuiteCases
derivTests = T.testGroup "derive" $ map (newTestCase AlgoDeriv) nonRecursiveTestCases
zipTests = T.testGroup "zip" $ map (newTestCase AlgoZip) nonRecursiveTestCases
mapTests = T.testGroup "map" $ map (newTestCase AlgoMap) nonRecursiveTestCases
vpaTests = T.testGroup "vpa" $ map (newTestCase AlgoVpa) nonRecursiveTestCases
in T.testGroup "Suite" [derivTests, zipTests, mapTests, vpaTests]
readTestCases :: IO [TestSuiteCase]
readTestCases = do {
path <- testPath;
exists <- doesDirectoryExist path;
if exists
then do {
jsondirs <- ls $ path </> "json";
xmldirs <- ls $ path </> "xml";
xmlTestCases <- mapM readXMLTest xmldirs;
jsonTestCases <- mapM readJsonTest jsondirs;
return $ jsonTestCases ++ xmlTestCases
} else return []
}
data TestSuiteCase = TestSuiteCase {
name :: String
, grammar :: Ast.Grammar
, input :: EncodedData
, valid :: Bool
} deriving Show
data EncodedData
= XMLData [XmlTree]
| JsonData [JsonTree]
deriving Show
data Algo = AlgoDeriv
| AlgoZip
| AlgoMap
| AlgoVpa
deriving Show
newTestCase :: Algo -> TestSuiteCase -> T.TestTree
newTestCase algo c@(TestSuiteCase name g (XMLData t) want) =
HUnit.testCase (testName algo c) $ testDeriv algo name g t want
newTestCase algo c@(TestSuiteCase name g (JsonData t) want) =
HUnit.testCase (testName algo c) $ testDeriv algo name g t want
testName :: Algo -> TestSuiteCase -> String
testName algo (TestSuiteCase name g t want) = name ++ "_" ++ show algo
testDeriv :: Tree t => Algo -> String -> Ast.Grammar -> [t] -> Bool -> IO ()
testDeriv AlgoDeriv name g ts want =
let p = either error id (do {
compiled <- compile g;
Derive.derive compiled ts;
})
got = nullable p
in HUnit.assertEqual ("want " ++ show want ++ " got " ++ show got ++ "\nstarting grammar = " ++ show g ++ "\nresulting derivative = " ++ show p) want got
testDeriv AlgoZip name g ts want =
let p = either error id (do {
compiled <- compile g;
Derive.zipderive compiled ts;
})
got = nullable p
in HUnit.assertEqual ("want " ++ show want ++ " got " ++ show got ++ "\nstarting grammar = " ++ show g ++ "\nresulting derivative = " ++ show p) want got
testDeriv AlgoMap name g ts want =
let p = either error id (do {
compiled <- compile g;
MemDerive.derive compiled ts;
})
got = nullable p
in HUnit.assertEqual ("want " ++ show want ++ " got " ++ show got ++ "\nstarting grammar = " ++ show g ++ "\nresulting derivative = " ++ show p) want got
testDeriv AlgoVpa name g ts want =
let p = either error id (do {
compiled <- compile g;
VpaDerive.derive compiled ts;
})
got = nullable p
in HUnit.assertEqual ("want " ++ show want ++ " got " ++ show got ++ "\nstarting grammar = " ++ show g ++ "\nresulting derivative = " ++ show p) want got
getRelapseJson :: [FilePath] -> FilePath
getRelapseJson paths = head $ filter (\fname -> takeExtension fname == ".json" && takeBaseName fname == "relapse") paths
getRelapse :: [FilePath] -> FilePath
getRelapse paths = head $ filter (\fname -> takeExtension fname == ".txt" && takeBaseName fname == "relapse") paths
isValidCase :: [FilePath] -> Bool
isValidCase paths = length (filter (\fname -> takeBaseName fname == "valid") paths) == 1
filepathWithExt :: [FilePath] -> String -> FilePath
filepathWithExt paths ext = head $ filter (\fname -> takeExtension fname == ext && takeBaseName fname /= "relapse") paths
fromGrammar :: String -> Ast.Grammar
fromGrammar s = case parseGrammar s of
(Left err) -> error $ "given input: <" ++ s ++ "> got parse error: " ++ show err
(Right g) -> g
readJsonTest :: FilePath -> IO TestSuiteCase
readJsonTest path = do {
files <- ls path;
grammarData <- readFile $ getRelapse files;
jsonData <- readFile $ filepathWithExt files ".json";
let jValue = case decodeJSON jsonData of
(Left e) -> error e
(Right r) -> r
;
return $ TestSuiteCase (takeBaseName path) (fromGrammar grammarData) (JsonData jValue) (isValidCase files)
}
readXMLTest :: FilePath -> IO TestSuiteCase
readXMLTest path = do {
files <- ls path;
grammarData <- readFile $ getRelapse files;
xmlData <- readFile $ filepathWithExt files ".xml";
return $ TestSuiteCase (takeBaseName path) (fromGrammar grammarData) (XMLData $ decodeXML xmlData) (isValidCase files)
}
ls :: FilePath -> IO [FilePath]
ls path = do {
dirs <- listDirectory path;
return $ map (path </>) dirs
}
testPath :: IO FilePath
testPath = do {
path <- getCurrentDirectory;
return $ takeDirectory path </> "testsuite" </> "relapse" </> "tests"
}