packages feed

sexpresso-1.0.0.2: test/Parse_Unittests.hs

module Parse_Unittests (
  parseTestTree
  )where

import Data.Void
import Data.Either
import Data.Bifunctor (first)
import Test.Tasty
import Test.Tasty.HUnit
import Text.Megaparsec as M
import Text.Megaparsec.Char
import Data.SExpresso.SExpr
import Data.SExpresso.Parse

type Parser = Parsec Void String

asciiLetter :: Parser Char
asciiLetter = oneOf (['a' .. 'z'] ++ ['A' .. 'Z'])

pIdent :: Parser String
pIdent = some asciiLetter

pDigit :: Parser String
pDigit = some digitChar

sexpParser :: SExprParser Parser () String
sexpParser = plainSExprParser (pIdent <|> pDigit)

pSExpr :: Parser (Sexp String)
pSExpr = parseSExpr sexpParser

pDecodeOne :: Parser (Sexp String)
pDecodeOne = decodeOne sexpParser

pDecode :: Parser [Sexp String]
pDecode = decode sexpParser

pOptionalSpace :: Parser (Sexp String)
pOptionalSpace = decodeOne $ setSpacingRule spaceIsOptional sexpParser

parseTestTree :: TestTree
parseTestTree = testGroup "Parse/Generic.hs & Parse/Char.hs unit tests" $
  let tparse :: Parser a -> String -> Either String a
      tparse p s = first M.errorBundlePretty $ M.parse p "" s

      sExprTests :: (Eq a, Show a) => Parser a -> (Sexp String -> a) -> [TestTree]
      sExprTests p f = [
        let s = "()" in testCase (show s) $ tparse p s @?= (Right $ f (SList () [])),
        let s = "(   )" in testCase (show s) $ tparse p s @?= (Right $ f (SList () [])),
        let s = "foo" in testCase (show s) $ tparse p s @?= (Right $ f (SAtom "foo")),
        let s = "1234" in testCase (show s) $ tparse p s @?= (Right $ f (SAtom "1234")),
        let s = "(foo)" in testCase (show s) $ tparse p s @?= (Right $ f (SList () [SAtom "foo"])),
        let s = "( foo)" in testCase (show s) $ tparse p s @?= (Right $ f (SList () [SAtom "foo"])),
        let s = "(foo )" in testCase (show s) $ tparse p s @?= (Right $ f (SList () [SAtom "foo"])),
        let s = "(foo bar baz)"
        in testCase (show s) $ tparse p s @?= (Right $ f (SList () [SAtom "foo", SAtom "bar", SAtom "baz"])),
        let s = "(foo (bar baz))"
        in testCase (show s) $ tparse p s @?=
           (Right $ f (SList () [SAtom "foo", SList () [SAtom "bar", SAtom "baz"]])),
        let s = "(foo(bar baz))"
        in testCase (show s) $ tparse p s @?=
           (Right $ f (SList () [SAtom "foo", SList () [SAtom "bar", SAtom "baz"]])),
        let s = "((foo bar)baz)"
        in testCase (show s) $ tparse p s @?=
           (Right $ f (SList () [SList () [SAtom "foo", SAtom "bar"], SAtom "baz"])),
        let s = "(foo1234)"
        in testCase (show s) $ (isLeft $ tparse p "(foo1234)") @? "Parsing must fail. foo and 1234 are not separated by whitespace"
        ]
                         
      decodeCommon :: (Eq a, Show a) => Parser a -> (Sexp String -> a) -> [TestTree]
      decodeCommon p f = [
        let s = " () " in testCase (show s) $ tparse p s @?= (Right $ f (SList () [])),
        let s = " ()" in testCase (show s) $ tparse p s @?= (Right $ f (SList () [])),
        let s = "() " in testCase (show s) $ tparse p s @?= (Right $ f (SList () [])),
        let s = "   ()   " in testCase (show s) $ tparse p s @?= (Right $ f (SList () []))
        ]
  in
    [
      testGroup "parseSExpr" $ sExprTests pSExpr id ++
      [
        let s = " foo"
        in testCase (show s) $ (isLeft $ tparse pSExpr s) @? "Parsing must fail. parseSExpr should not parse whitespace"
      ],
      testGroup "decondeOne" $ sExprTests pDecodeOne id ++
      decodeCommon pDecodeOne id ++
      [
        let s = "() err" in testCase (show s) $ (isLeft $ tparse pDecodeOne s) @? "Parsing must fail. 2 SExpr",
        let s = "err ()" in testCase (show s) $ (isLeft $ tparse pDecodeOne s) @? "Parsing must fail. 2 SExpr",
        let s = "()err" in testCase (show s) $ (isLeft $ tparse pDecodeOne s) @? "Parsing must fail. 2 SExpr",
        let s = "err()" in testCase (show s) $ (isLeft $ tparse pDecodeOne s) @? "Parsing must fail. 2 SExpr"
      ],
     testGroup "decode" $ sExprTests pDecode (\x -> [x]) ++
     decodeCommon pDecode (\x -> [x]) ++
      [
        let s = "()()" in testCase (show s) $ tparse pDecode s @?= Right [SList () [], SList () []],
        let s = " ()()" in testCase (show s) $ tparse pDecode s @?= Right [SList () [], SList () []],
        let s = "() ()" in testCase (show s) $ tparse pDecode s @?= Right [SList () [], SList () []],
        let s = "()() " in testCase (show s) $ tparse pDecode s @?= Right [SList () [], SList () []],
        let s = "  ()  ()  " in testCase (show s) $ tparse pDecode s @?= Right [SList () [], SList () []],
        let s = "(foo)(1234)" in testCase (show s) $ tparse pDecode s @?= Right [SList () [SAtom "foo"], SList () [SAtom "1234"]],
        let s = " (foo)(1234)" in testCase (show s) $ tparse pDecode s @?= Right [SList () [SAtom "foo"], SList () [SAtom "1234"]],
        let s = "(foo) (1234)" in testCase (show s) $ tparse pDecode s @?= Right [SList () [SAtom "foo"], SList () [SAtom "1234"]],
        let s = "(foo)(1234) " in testCase (show s) $ tparse pDecode s @?= Right [SList () [SAtom "foo"], SList () [SAtom "1234"]],
        let s = "  (foo)  (1234)  " in testCase (show s) $ tparse pDecode s @?= Right [SList () [SAtom "foo"], SList () [SAtom "1234"]],
        let s = "(foo) 1234" in testCase (show s) $ tparse pDecode s @?= Right [SList () [SAtom "foo"], SAtom "1234"],
        let s = "foo 1234" in testCase (show s) $ tparse pDecode s @?= Right [SAtom "foo", SAtom "1234"],
        let s = "foo(1234)" in testCase (show s) $ tparse pDecode s @?= Right [SAtom "foo", SList () [SAtom "1234"]],
        let s = "(foo)1234" in testCase (show s) $ tparse pDecode s @?= Right [SList () [SAtom "foo"], SAtom "1234"],
        let s = "bar1234"
        in testCase (show s) $ (isLeft $ tparse pDecode s) @? "Parsing must fail. bar and 1234 are not separated by whitespace"
      ],
     testGroup "spaceIsOptional" $ [
        let s = "(foo1234)"
        in testCase (show s) $ tparse pOptionalSpace s @?= (Right (SList () [SAtom "foo", SAtom "1234"])),
        let s = "(foo 1234)"
        in testCase (show s) $ tparse pOptionalSpace s @?= (Right (SList () [SAtom "foo", SAtom "1234"])),
        let s = "(foo1234 bar)"
        in testCase (show s) $ tparse pOptionalSpace s @?= (Right (SList () [SAtom "foo", SAtom "1234", SAtom "bar"])),
        let s = "( foo1234 )"
        in testCase (show s) $ tparse pOptionalSpace s @?= (Right (SList () [SAtom "foo", SAtom "1234"]))
        ]
  ]