{-# 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 , parseConduitCase , parseConduitErrorCase -- , parseOrSkipCase ] 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 -- parseOrSkipCase :: TestTree -- parseOrSkipCase = testCase "parseOrSkip" $ do -- result <- runResourceT . runConduit $ sourceList [1 :: Int, 10, 2, 9, 3, 8, 4, 7, 5, 6] =$= parser `parseOrSkip` anyOne =$= consume -- result @?= [10, 9, 8, 7, 6] -- where parser = do -- integer <- await -- if integer >= 6 then return integer else unexpected "Invalid integer" parseConduitCase :: TestTree parseConduitCase = testCase "parseConduit" $ do result <- runResourceT . runConduit $ sourceList [1 :: Int, 2, 3, 4, 5, 6, 7, 8, 9, 10] =$= parseC parser =$= consume result @?= [Left 1, Right 2, Left 3, Right 4, Left 5, Right 6, Left 7, Right 8, Left 9, Right 10] where parser = do integer <- await return $ (if odd integer then Left else Right) integer parseConduitErrorCase :: TestTree parseConduitErrorCase = testCase "parseConduitError" $ do result <- Exception.try . runResourceT . runConduit $ sourceList [1 :: Int, 2, 3, 4, 5, 6, 7, 8, 9, 10] =$= parseC parser =$= consume result @?= (Left (Unexpected "Wrong integer") :: Either ConduitParserException [Int]) where parser = await >> throw (Unexpected "Wrong integer")