|
Packit |
4b2029 |
{-# LANGUAGE CPP #-}
|
|
Packit |
4b2029 |
{-# LANGUAGE OverloadedStrings #-}
|
|
Packit |
4b2029 |
{-# LANGUAGE TupleSections #-}
|
|
Packit |
4b2029 |
{-# OPTIONS_GHC -fno-warn-incomplete-patterns #-}
|
|
Packit |
4b2029 |
module Data.Conduit.AttoparsecSpec (spec) where
|
|
Packit |
4b2029 |
import Control.Exception (fromException)
|
|
Packit |
4b2029 |
import Test.Hspec
|
|
Packit |
4b2029 |
|
|
Packit |
4b2029 |
import Control.Applicative ((<*), (<|>))
|
|
Packit |
4b2029 |
import Control.Monad
|
|
Packit |
4b2029 |
import Control.Monad.Trans.Resource (runExceptionT)
|
|
Packit |
4b2029 |
import qualified Data.Attoparsec.ByteString.Char8
|
|
Packit |
4b2029 |
import qualified Data.Attoparsec.Text
|
|
Packit |
4b2029 |
import Data.Conduit
|
|
Packit |
4b2029 |
import Data.Conduit.Attoparsec
|
|
Packit |
4b2029 |
import qualified Data.Conduit.List as CL
|
|
Packit |
4b2029 |
|
|
Packit |
4b2029 |
spec :: Spec
|
|
Packit |
4b2029 |
spec = describe "Data.Conduit.AttoparsecSpec" $ do
|
|
Packit |
4b2029 |
describe "error position" $ do
|
|
Packit |
4b2029 |
it "works for text" $ do
|
|
Packit |
4b2029 |
let input = ["aaa\na", "aaa\n\n", "aaa", "aab\n\naaaa"]
|
|
Packit |
4b2029 |
badLine = 4
|
|
Packit |
4b2029 |
badCol = 6
|
|
Packit |
4b2029 |
badOff = 15
|
|
Packit |
4b2029 |
parser = Data.Attoparsec.Text.endOfInput <|> (Data.Attoparsec.Text.notChar 'b' >> parser)
|
|
Packit |
4b2029 |
sink = sinkParser parser
|
|
Packit |
4b2029 |
sink' = sinkParserEither parser
|
|
Packit |
4b2029 |
ea <- runExceptionT $ CL.sourceList input $$ sink
|
|
Packit |
4b2029 |
case ea of
|
|
Packit |
4b2029 |
Left e ->
|
|
Packit |
4b2029 |
case fromException e of
|
|
Packit |
4b2029 |
Just pe -> do
|
|
Packit |
4b2029 |
errorPosition pe `shouldBe` Position badLine badCol badOff
|
|
Packit |
4b2029 |
ea' <- CL.sourceList input $$ sink'
|
|
Packit |
4b2029 |
case ea' of
|
|
Packit |
4b2029 |
Left pe ->
|
|
Packit |
4b2029 |
errorPosition pe `shouldBe` Position badLine badCol badOff
|
|
Packit |
4b2029 |
it "works for bytestring" $ do
|
|
Packit |
4b2029 |
let input = ["aaa\na", "aaa\n\n", "aaa", "aab\n\naaaa"]
|
|
Packit |
4b2029 |
badLine = 4
|
|
Packit |
4b2029 |
badCol = 6
|
|
Packit |
4b2029 |
badOff = 15
|
|
Packit |
4b2029 |
parser = Data.Attoparsec.ByteString.Char8.endOfInput <|> (Data.Attoparsec.ByteString.Char8.notChar 'b' >> parser)
|
|
Packit |
4b2029 |
sink = sinkParser parser
|
|
Packit |
4b2029 |
sink' = sinkParserEither parser
|
|
Packit |
4b2029 |
ea <- runExceptionT $ CL.sourceList input $$ sink
|
|
Packit |
4b2029 |
case ea of
|
|
Packit |
4b2029 |
Left e ->
|
|
Packit |
4b2029 |
case fromException e of
|
|
Packit |
4b2029 |
Just pe -> do
|
|
Packit |
4b2029 |
errorPosition pe `shouldBe` Position badLine badCol badOff
|
|
Packit |
4b2029 |
ea' <- CL.sourceList input $$ sink'
|
|
Packit |
4b2029 |
case ea' of
|
|
Packit |
4b2029 |
Left pe ->
|
|
Packit |
4b2029 |
errorPosition pe `shouldBe` Position badLine badCol badOff
|
|
Packit |
4b2029 |
it "works in last chunk" $ do
|
|
Packit |
4b2029 |
let input = ["aaa\na", "aaa\n\n", "aaa", "aab\n\naaaa"]
|
|
Packit |
4b2029 |
badLine = 6
|
|
Packit |
4b2029 |
badCol = 5
|
|
Packit |
4b2029 |
badOff = 22
|
|
Packit |
4b2029 |
parser = Data.Attoparsec.Text.char 'c' <|> (Data.Attoparsec.Text.anyChar >> parser)
|
|
Packit |
4b2029 |
sink = sinkParser parser
|
|
Packit |
4b2029 |
sink' = sinkParserEither parser
|
|
Packit |
4b2029 |
ea <- runExceptionT $ CL.sourceList input $$ sink
|
|
Packit |
4b2029 |
case ea of
|
|
Packit |
4b2029 |
Left e ->
|
|
Packit |
4b2029 |
case fromException e of
|
|
Packit |
4b2029 |
Just pe -> do
|
|
Packit |
4b2029 |
errorPosition pe `shouldBe` Position badLine badCol badOff
|
|
Packit |
4b2029 |
ea' <- CL.sourceList input $$ sink'
|
|
Packit |
4b2029 |
case ea' of
|
|
Packit |
4b2029 |
Left pe ->
|
|
Packit |
4b2029 |
errorPosition pe `shouldBe` Position badLine badCol badOff
|
|
Packit |
4b2029 |
it "works in last chunk" $ do
|
|
Packit |
4b2029 |
let input = ["aaa\na", "aaa\n\n", "aaa", "aa\n\naaaab"]
|
|
Packit |
4b2029 |
badLine = 6
|
|
Packit |
4b2029 |
badCol = 6
|
|
Packit |
4b2029 |
badOff = 22
|
|
Packit |
4b2029 |
parser = Data.Attoparsec.Text.string "bc" <|> (Data.Attoparsec.Text.anyChar >> parser)
|
|
Packit |
4b2029 |
sink = sinkParser parser
|
|
Packit |
4b2029 |
sink' = sinkParserEither parser
|
|
Packit |
4b2029 |
ea <- runExceptionT $ CL.sourceList input $$ sink
|
|
Packit |
4b2029 |
case ea of
|
|
Packit |
4b2029 |
Left e ->
|
|
Packit |
4b2029 |
case fromException e of
|
|
Packit |
4b2029 |
Just pe -> do
|
|
Packit |
4b2029 |
errorPosition pe `shouldBe` Position badLine badCol badOff
|
|
Packit |
4b2029 |
ea' <- CL.sourceList input $$ sink'
|
|
Packit |
4b2029 |
case ea' of
|
|
Packit |
4b2029 |
Left pe ->
|
|
Packit |
4b2029 |
errorPosition pe `shouldBe` Position badLine badCol badOff
|
|
Packit |
4b2029 |
it "works after new line in text" $ do
|
|
Packit |
4b2029 |
let input = ["aaa\n", "aaa\n\n", "aaa", "aa\nb\naaaa"]
|
|
Packit |
4b2029 |
badLine = 5
|
|
Packit |
4b2029 |
badCol = 1
|
|
Packit |
4b2029 |
badOff = 15
|
|
Packit |
4b2029 |
parser = Data.Attoparsec.Text.endOfInput <|> (Data.Attoparsec.Text.notChar 'b' >> parser)
|
|
Packit |
4b2029 |
sink = sinkParser parser
|
|
Packit |
4b2029 |
sink' = sinkParserEither parser
|
|
Packit |
4b2029 |
ea <- runExceptionT $ CL.sourceList input $$ sink
|
|
Packit |
4b2029 |
case ea of
|
|
Packit |
4b2029 |
Left e ->
|
|
Packit |
4b2029 |
case fromException e of
|
|
Packit |
4b2029 |
Just pe -> do
|
|
Packit |
4b2029 |
errorPosition pe `shouldBe` Position badLine badCol badOff
|
|
Packit |
4b2029 |
ea' <- CL.sourceList input $$ sink'
|
|
Packit |
4b2029 |
case ea' of
|
|
Packit |
4b2029 |
Left pe ->
|
|
Packit |
4b2029 |
errorPosition pe `shouldBe` Position badLine badCol badOff
|
|
Packit |
4b2029 |
it "works after new line in bytestring" $ do
|
|
Packit |
4b2029 |
let input = ["aaa\n", "aaa\n\n", "aaa", "aa\nb\naaaa"]
|
|
Packit |
4b2029 |
badLine = 5
|
|
Packit |
4b2029 |
badCol = 1
|
|
Packit |
4b2029 |
badOff = 15
|
|
Packit |
4b2029 |
parser = Data.Attoparsec.ByteString.Char8.endOfInput <|> (Data.Attoparsec.ByteString.Char8.notChar 'b' >> parser)
|
|
Packit |
4b2029 |
sink = sinkParser parser
|
|
Packit |
4b2029 |
sink' = sinkParserEither parser
|
|
Packit |
4b2029 |
ea <- runExceptionT $ CL.sourceList input $$ sink
|
|
Packit |
4b2029 |
case ea of
|
|
Packit |
4b2029 |
Left e ->
|
|
Packit |
4b2029 |
case fromException e of
|
|
Packit |
4b2029 |
Just pe -> do
|
|
Packit |
4b2029 |
errorPosition pe `shouldBe` Position badLine badCol badOff
|
|
Packit |
4b2029 |
ea' <- CL.sourceList input $$ sink'
|
|
Packit |
4b2029 |
case ea' of
|
|
Packit |
4b2029 |
Left pe ->
|
|
Packit |
4b2029 |
errorPosition pe `shouldBe` Position badLine badCol badOff
|
|
Packit |
4b2029 |
it "works for first line" $ do
|
|
Packit |
4b2029 |
let input = ["aab\na", "aaa\n\n", "aaa", "aab\n\naaaa"]
|
|
Packit |
4b2029 |
badLine = 1
|
|
Packit |
4b2029 |
badCol = 3
|
|
Packit |
4b2029 |
badOff = 2
|
|
Packit |
4b2029 |
parser = Data.Attoparsec.Text.endOfInput <|> (Data.Attoparsec.Text.notChar 'b' >> parser)
|
|
Packit |
4b2029 |
sink = sinkParser parser
|
|
Packit |
4b2029 |
sink' = sinkParserEither parser
|
|
Packit |
4b2029 |
ea <- runExceptionT $ CL.sourceList input $$ sink
|
|
Packit |
4b2029 |
case ea of
|
|
Packit |
4b2029 |
Left e ->
|
|
Packit |
4b2029 |
case fromException e of
|
|
Packit |
4b2029 |
Just pe -> do
|
|
Packit |
4b2029 |
errorPosition pe `shouldBe` Position badLine badCol badOff
|
|
Packit |
4b2029 |
ea' <- CL.sourceList input $$ sink'
|
|
Packit |
4b2029 |
case ea' of
|
|
Packit |
4b2029 |
Left pe ->
|
|
Packit |
4b2029 |
errorPosition pe `shouldBe` Position badLine badCol badOff
|
|
Packit |
4b2029 |
|
|
Packit |
4b2029 |
describe "conduitParser" $ do
|
|
Packit |
4b2029 |
it "parses a repeated stream" $ do
|
|
Packit |
4b2029 |
let input = ["aaa\n", "aaa\naaa\n", "aaa\n"]
|
|
Packit |
4b2029 |
parser = Data.Attoparsec.Text.string "aaa" <* Data.Attoparsec.Text.endOfLine
|
|
Packit |
4b2029 |
sink = conduitParserEither parser =$= CL.consume
|
|
Packit |
4b2029 |
(Right ea) <- runExceptionT $ CL.sourceList input $$ sink
|
|
Packit |
4b2029 |
let chk a = case a of
|
|
Packit |
4b2029 |
Left{} -> False
|
|
Packit |
4b2029 |
Right (_, xs) -> xs == "aaa"
|
|
Packit |
4b2029 |
chkp l = PositionRange (Position l 1 ((l - 1) * 4)) (Position (l+1) 1 (l * 4))
|
|
Packit |
4b2029 |
forM_ ea $ \ a -> a `shouldSatisfy` chk :: Expectation
|
|
Packit |
4b2029 |
forM_ (zip ea [1..]) $ \ (Right (pos, _), l) -> pos `shouldBe` chkp l
|
|
Packit |
4b2029 |
length ea `shouldBe` 4
|
|
Packit |
4b2029 |
|
|
Packit |
4b2029 |
it "positions on first line" $ do
|
|
Packit |
4b2029 |
results <- yield "hihihi\nhihi"
|
|
Packit |
4b2029 |
$$ conduitParser (Data.Attoparsec.Text.string "\n" <|> Data.Attoparsec.Text.string "hi")
|
|
Packit |
4b2029 |
=$ CL.consume
|
|
Packit |
4b2029 |
let f (a, b, c, d, e, f, g) = (PositionRange (Position a b c) (Position d e f), g)
|
|
Packit |
4b2029 |
results `shouldBe` map f
|
|
Packit |
4b2029 |
[ (1, 1, 0, 1, 3, 2, "hi")
|
|
Packit |
4b2029 |
, (1, 3, 2, 1, 5, 4, "hi")
|
|
Packit |
4b2029 |
, (1, 5, 4, 1, 7, 6, "hi")
|
|
Packit |
4b2029 |
|
|
Packit |
4b2029 |
, (1, 7, 6, 2, 1, 7, "\n")
|
|
Packit |
4b2029 |
|
|
Packit |
4b2029 |
, (2, 1, 7, 2, 3, 9, "hi")
|
|
Packit |
4b2029 |
, (2, 3, 9, 2, 5, 11, "hi")
|
|
Packit |
4b2029 |
]
|