packages feed

hedn-0.1.4.1: tests/TestParser.hs

{-# LANGUAGE OverloadedStrings, Rank2Types #-}

module Main where

import Data.Attoparsec.Lazy as A
import qualified Data.ByteString.Lazy.Char8 as BSL

import Data.EDN.Parser as P
import Data.EDN.Types as E

import Control.Monad (forM_)
import qualified System.Console.ANSI as ANSI

main :: IO ()
main = forM_ cases $ checkCase (parse P.parseTagged) (parserResult)

parserResult :: Eq a => Result a -> a -> Bool
parserResult result output = case result of
    Done "" o -> o == output
    _         -> False

checkCase :: forall a a1. (Show a1, Show a) => (BSL.ByteString -> a1)
                                            -> (a1 -> a -> Bool)
                                            -> (BSL.ByteString, a)
                                            -> IO ()
checkCase runner checker (input, output) = do
    putStr "Checking: '"
    BSL.putStr input
    putStrLn "'"

    putStrLn $ "Should be: " ++ show output

    let result = runner input
    let correct = checker result output

    ANSI.setSGR [ANSI.SetColor ANSI.Foreground ANSI.Vivid (if correct then ANSI.Green else ANSI.Red)]
    putStr "Result: "
    ANSI.setSGR [ANSI.Reset]
    print result
    putStrLn ""

cases :: [(BSL.ByteString, E.TaggedValue)]
cases = [ ("nil", E.nil)

        , ("true", E.true)
        , ("false", E.false)

        , ("\"a nice string\"", "a nice string")
        , ("\"split\\second \\t\\rai\\n\"", "split\\second \t\rai\n")
        , ("\"test \\\"sausage\\\" shmest\"", "test \"sausage\" shmest")
        , ("\"\"", "")

        , ("\\c", E.char 'c')
        , ("\\\\", E.char '\\')
        , ("\\newline", E.char '\n')
        , ("\\space", E.char ' ')
        , ("\\tab", E.char '\t')

        , ("justasymbol", E.symbol "justasymbol")
        , ("with#stuff:inside", E.symbol "with#stuff:inside")
        , ("my-namespace/foo", E.symbolNS "my-namespace" "foo")
        , ("/", E.symbol "/")

        , (":fred", E.keyword "fred")
        , (":my/fred", E.keyword "my/fred")

        , ("42", E.integer 42)
        , ("-1", E.integer (-1))

        , ("100.50", E.floating 100.5)
        , ("-3.14", E.floating (-3.14))
         -- ...and many other strange stuff...

        , ("(a b 42)", sampleList)
        , ("()", E.notag $ E.makeList [])

        , ("[a b 42]", sampleVec)
        , ("[]", E.notag $ E.makeVec [])

        , ("{:a 1, \"foo\" :bar, [1 2 3] four}", sampleMap)
        , ("{}", E.notag $ E.makeMap [])

        , ("#{a b [1 2 3]}", sampleSet)
        , ("#{}", E.notag $ E.makeSet [])

        , ("[a b #_foo 42]", sampleDiscard)
        , ("(1 2 ;more to go!\n 3 4)", sampleComment)

        , ("#myapp/Person {:first \"Fred\" :last \"Mertz\"}", E.tag "myapp" "Person" sampleTaggedMap)
        , ("{:first \"Fred\" :last \"Mertz\"}", E.notag sampleTaggedMap)
        ]

sampleList :: E.TaggedValue
sampleList = E.notag $ E.makeList [E.symbol "a", E.symbol "b", E.integer 42]

sampleVec :: E.TaggedValue
sampleVec = E.notag $ E.makeVec [E.symbol "a", E.symbol "b", E.integer 42]

sampleMap :: E.TaggedValue
sampleMap = E.notag $ E.makeMap [ (":a",                                              E.integer 1)
                                , ("foo",                                             E.keyword "bar")
                                , (E.makeVec [E.integer 1, E.integer 2, E.integer 3], E.symbol "four")
                                ]

sampleSet :: E.TaggedValue
sampleSet = E.notag $ E.makeSet [ E.symbol "a"
                                , E.symbol "b"
                                , E.notag $ E.makeVec [E.integer 1, E.integer 2, E.integer 3]
                                ]

sampleDiscard :: E.TaggedValue
sampleDiscard = E.notag $ E.makeVec [E.symbol "a", E.symbol "b", E.integer 42]

sampleComment :: E.TaggedValue
sampleComment = E.notag $ E.makeList [E.integer 1, E.integer 2, E.integer 3, E.integer 4]

sampleTaggedMap :: E.Value
sampleTaggedMap = E.makeMap [ "first" ..= "Fred", "last" ..= "Mertz" ]