json-autotype-3.0.0: test/TestExamples.hs
-- Test over all files in examples/ directory
module Main(main) where
import Control.Monad(forM, forM_, unless, join)
import Data.Char(toUpper)
import Data.Functor ((<$>))
import Data.List(isPrefixOf, isSuffixOf)
import System.Directory(doesDirectoryExist, getDirectoryContents, createDirectoryIfMissing)
import System.FilePath((</>), (<.>), takeBaseName, replaceFileName)
import System.Exit(ExitCode(..))
import System.Environment as Env
import System.Process (rawSystem)
import Data.Aeson.AutoType.CodeGen(runModule, Lang(Haskell))
import Data.Aeson ( Result, Object, FromJSON, Value(Null,Number), (.:?) )
import Data.Aeson.Types ( Parser, parse )
import Data.Text ( Text, pack )
import Data.HashMap.Lazy ( singleton, empty )
-- | <http://book.realworldhaskell.org/read/io-case-study-a-library-for-searching-the-filesystem.html>
getRecursiveContents :: FilePath -> IO [FilePath]
getRecursiveContents topdir = do
ex<-doesDirectoryExist topdir
if ex
then do
names <- getDirectoryContents topdir
let properNames = filter (not . isPrefixOf ".") names
paths <- forM properNames $ \name -> do
let path = topdir </> name
isDirectory <- doesDirectoryExist path
if isDirectory
then getRecursiveContents path
else return [path]
return (concat paths)
else return []
capitalize :: String -> String
capitalize [] = []
capitalize (s:ss) = toUpper s:ss
main :: IO ()
main = do
verifyAesonOperators
filenames <- filter (isSuffixOf ".json")
<$> getRecursiveContents "examples"
createDirectoryIfMissing True "output"
forM_ filenames $ \filename -> do
let outputFilename = ("output" </> capitalize (takeBaseName filename <.> "hs"))
genResult <- runAutotype [filename, "--outputFilename", outputFilename]
unless (genResult == ExitSuccess) $
fail (unwords ["test case", show filename, "failed with", show genResult])
parserResult <- runModule Haskell [outputFilename, filename]
-- ^ runModule HaskellStrict -- for compiling with -Wall -Werror
unless (parserResult == ExitSuccess) $
fail (unwords ["generated parser", show outputFilename, "failed with", show parserResult])
runAutotype :: [String] -> IO ExitCode
runAutotype arguments = do
stackEnv <- doesDirectoryExist ".stack-work"
cabalEnv <- doesDirectoryExist "dist/build/autogen"
maybeStack <- Env.lookupEnv "STACK_EXEC"
let (exec, args) | Just stackExec <- maybeStack = (stackExec, ["run","--" ])
| stackEnv = ("stack", ["run","--" ])
| cabalEnv = ("cabal", ["run","--" ])
| otherwise = error "This test must be run either in Stack or Cabal environment."
putStrLn $ concat ["Running json-autotype with executable ", show exec, " and arguments ", show args]
rawSystem exec $ args ++ arguments
verifyAesonOperators :: IO ()
verifyAesonOperators = do
parseTest (singleton (pack "foo") (Number 1))
parseTest (singleton (pack "foo") Null )
parseTest (singleton (pack "bar") Null )
parseTest empty
(.:??) :: FromJSON a => Object -> Text -> Parser (Maybe a)
o .:?? val = fmap join (o .:? val)
parseTest :: Object -> IO ()
parseTest o = unless (r1 == r2) (fail (show r1 ++ " /= " ++ show r2))
where r1, r2 :: Result (Maybe Int)
r1 = parse (.:? (pack "foo")) o
r2 = parse (.:?? (pack "foo")) o