ampersand-3.1.0: src/Database/Design/Ampersand/Test/TestScripts.hs
{-# LANGUAGE Rank2Types, NoMonomorphismRestriction, ScopedTypeVariables #-}
module Database.Design.Ampersand.Test.TestScripts (getTestScripts,testAmpersandScripts) where
import Data.List
import Data.Char(toUpper)
import System.FilePath ((</>),takeExtension)
import Control.Monad --(filterM, forM_, foldM,when)
import Control.Exception.Base
import System.IO.Error (tryIOError)
import System.Directory (getDirectoryContents, doesFileExist, doesDirectoryExist)
import Control.Monad.Trans.Class (lift)
import Data.Conduit
import Database.Design.Ampersand.Test.RunAmpersand (ampersand)
import Database.Design.Ampersand.Input.ADL1.CtxError
--endswith :: String -> String -> Bool
--endswith a b = drop (length a - length b) a == b
-- Returns tuple with files and subdirectories inside the given directory
--getDirectory :: FilePath -> IO ([FilePath],[FilePath])
--getDirectory path =
-- do contents <- getDirectoryContents path
-- let valid = filter (\x-> x /= "." && x /= "..") contents
-- let paths = map (path ++) valid
-- files <- filterM doesFileExist paths
-- subdirs <- filterM doesDirectoryExist paths
-- return (sort files, sort subdirs)
--getFiles :: String -> FilePath -> IO [FilePath]
--getFiles ext dir =
-- do (fs, ds) <- getDirectory (dir++"/")
-- let files = filter (`endswith` ext) fs
-- foldM recursive files ds
-- where recursive rs d =
-- do ms <- getFiles ext d
-- return $ ms ++ rs
getTestScripts :: IO [FilePath]
getTestScripts = do
-- fs <- getFiles ".adl" "ArchitectureAndDesign"
-- ss <- getFiles ".adl" $ ".." </> "ampersand-models" </> "Tests" </> "ShouldSucceed"
-- ds <- getFiles ".adl" $ "AmpersandData" </> "FormalAmpersand"
return $ [] --enabling these test as a single testcase will stop the sentinel from working. Was: fs ++ ss ++ ds -- ++ models
data DirContent = DirList [FilePath] [FilePath]
| DirError IOError
data DirData = DirData FilePath DirContent
testAmpersandScripts :: IO ()
testAmpersandScripts
= do
walk baseDir $$ myVisitor
where
baseDir = ".." </> "ampersand-models"
-- Produces directory data
walk :: FilePath -> Source IO DirData
walk path = do
result <- lift $ tryIOError listdir
case result of
Right dl
-> case dl of
DirList subdirs _
-> do
yield (DirData path dl)
forM_ subdirs (walk . (path </>))
DirError err
-> yield (DirData path (DirError err))
Left err
-> yield (DirData path (DirError err))
where
listdir = do
entries <- getDirectoryContents path >>= filterHidden
subdirs <- filterM isDir entries
files <- filterM isFile entries
return $ DirList subdirs (filter isRelevant files)
where
isFile entry = doesFileExist (path </> entry)
isDir entry = doesDirectoryExist (path </> entry)
filterHidden paths = return $ filter (not.isHidden) paths
isRelevant f = map toUpper (takeExtension f) `elem` [".ADL"]
isHidden dir = head dir == '.'
-- Consume directories
myVisitor :: Sink DirData IO ()
myVisitor = addCleanup (\_ -> putStrLn "Finished.") $ loop 1
where
loop :: Int -> ConduitM DirData a IO ()
loop n = do
lift $ putStr $ ">> " ++ show n ++ ". "
mr <- await
case mr of
Nothing -> return ()
Just r -> lift (process r) >> loop (n + 1)
process (DirData path (DirError err)) = do
putStrLn $ "I've tried to look in " ++ path ++ "."
putStrLn $ " There was an error: "
putStrLn $ " " ++ show err
process (DirData path (DirList dirs files)) = do
putStrLn $ path ++ ". ("++ show (length dirs) ++ " directorie(s) and " ++ show (length files) ++ " relevant file(s):"
forM_ files (runATest path)
runATest :: FilePath -> FilePath -> IO()
runATest path file =
catch (runATest' path file) showError
where
showError :: SomeException -> IO()
showError err
= do putStrLn "***** ERROR: Fatal error was thrown: *****"
putStrLn $ (path </> file)
putStrLn $ show err
putStrLn "******************************************"
runATest' :: FilePath -> FilePath -> IO()
runATest' path file = do
[(_,errs)] <- ampersand [path </> file]
putStrLn
( file ++": "++
case (shouldFail,errs) of
(False, []) -> "OK. => Pass"
(False, _ ) -> "Fail => NOT PASSED:"
(True , []) -> "Ok. => NOT PASSED"
(True , _ ) -> "Fail => Pass"
)
when (not shouldFail) $ mapM_ putStrLn (map showErr (take 1 errs)) --for now, only show the first error
where shouldFail = "SHOULDFAIL" `isInfixOf` map toUpper (path </> file)