{-# LANGUAGE OverloadedLists #-} {-# LANGUAGE OverloadedStrings #-} import Control.Applicative import Control.Exception.Safe as Exception import Control.Monad.Error.Class import Control.Monad.Trans.Resource import Data.Conduit hiding (await, leftover) import Data.Conduit.List hiding (peek) import Data.Conduit.Parser import Test.Tasty import Test.Tasty.HUnit -- import Test.Tasty.QuickCheck import Text.Parser.Combinators main :: IO () main = defaultMain $ testGroup "Tests" [ unitTests -- , properties ] unitTests :: TestTree unitTests = testGroup "Unit tests" [ awaitCase , peekCase , leftoverCase , errorCase , alternativeCase , catchCase , parsingCase ] awaitCase :: TestTree awaitCase = testCase "await" $ do i <- runResourceT . runConduit $ sourceList [1 :: Int] .| runConduitParser parser i @=? (1, Nothing) where parser = (,) <$> await <*> optional await peekCase :: TestTree peekCase = testCase "peek" $ do result <- runResourceT . runConduit $ sourceList [1 :: Int, 2] .| runConduitParser parser result @=? (Just 1, 1, 2, Nothing) where parser = (,,,) <$> peek <*> await <*> await <*> peek leftoverCase :: TestTree leftoverCase = testCase "leftover" $ do result <- runResourceT . runConduit $ sourceList [1 :: Int, 2, 3] .| runConduitParser parser result @?= (3, 2, 1) where parser = do (a, b, c) <- (,,) <$> await <*> await <*> await leftover a >> leftover b >> leftover c (,,) <$> await <*> await <*> await errorCase :: TestTree errorCase = testCase "error" $ do result1 <- Exception.try . runResourceT . runConduit $ sourceList [] .| runConduitParser parser result2 <- Exception.try . runResourceT . runConduit $ sourceList [] .| runConduitParser (parser "Name1") result3 <- Exception.try . runResourceT . runConduit $ sourceList [] .| runConduitParser ((parser "Name1") "Name2") result1 @?= Left (Unexpected "ERROR") result2 @?= Left (NamedParserException "Name1" $ Unexpected "ERROR") result3 @?= Left (NamedParserException "Name2" $ NamedParserException "Name1" $ Unexpected "ERROR") where parser = unexpected "ERROR" >> return (1 :: Int) alternativeCase :: TestTree alternativeCase = testCase "alternative" $ do result <- runResourceT . runConduit $ sourceList [1 :: Int, 2, 3] .| runConduitParser parser result @?= (1, 2, Nothing) where parser = do a <- parseInt 1 <|> parseInt 2 b <- parseInt 1 <|> parseInt 2 c <- optional $ parseInt 1 <|> parseInt 2 await eof return (a, b, c) parseInt :: (Monad m) => Int -> ConduitParser Int m Int parseInt i = do a <- await if i == a then return a else unexpected ("Expected " ++ show i ++ ", got " ++ show a) catchCase :: TestTree catchCase = testCase "catch" $ do result <- runResourceT . runConduit $ sourceList [1 :: Int, 2] .| runConduitParser parser result @?= (1, 2) where parser = catchError (await >> await >> throwError (Unexpected "ERROR")) . const $ (,) <$> await <*> await parsingCase :: TestTree parsingCase = testCase "parsing" $ do result <- runResourceT . runConduit $ sourceList [1 :: Int, 2] .| runConduitParser parser result @?= (1, 2) where parser = (,) <$> await <*> await <* notFollowedBy await <* eof