pinch-0.3.2.0: tests/Pinch/Internal/ParserSpec.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE NegativeLiterals #-}
{-# LANGUAGE OverloadedStrings #-}
module Pinch.Internal.ParserSpec (spec) where
#if __GLASGOW_HASKELL__ < 709
import Control.Applicative
#endif
import Data.Either (isLeft)
import Data.Word (Word8)
import Test.Hspec
import Test.Hspec.QuickCheck
import Test.QuickCheck
import qualified Data.ByteString as B
import Pinch.Arbitrary
import qualified Pinch.Internal.Parser as P
parse :: [Word8] -> P.Parser a -> Either String a
parse s p = P.runParser p (B.pack s)
parseCases
:: (Show a, Eq a)
=> P.Parser a -> [([Word8], a)] -> Expectation
parseCases parser = mapM_ . uncurry $ \bytes expected ->
(bytes `parse` parser) `shouldBe` Right expected
spec :: Spec
spec = describe "Parser" $ do
it "can succeed" $
P.runParser (return 42) "" `shouldBe` Right (42 :: Int)
it "can fail" $
(P.runParser (fail "great sadness") "" :: Either String ())
`shouldBe` Left "great sadness"
it "can parse 8-bit integers" $
parseCases P.int8
[ ([0x01], 1)
, ([0x05], 5)
, ([0x7f], 127)
, ([0xff], -1)
, ([0x80], -128)
]
it "can parse 16-bit integers" $
parseCases P.int16
[ ([0x00, 0x01], 1)
, ([0x00, 0xff], 255)
, ([0x01, 0x00], 256)
, ([0x01, 0x01], 257)
, ([0x7f, 0xff], 32767)
, ([0xff, 0xff], -1)
, ([0xff, 0xfe], -2)
, ([0xff, 0x00], -256)
, ([0xff, 0x01], -255)
, ([0x80, 0x00], -32768)
]
it "can parse 32-bit integers" $
parseCases P.int32
[ ([0x00, 0x00, 0x00, 0x01], 1)
, ([0x00, 0x00, 0x00, 0xff], 255)
, ([0x00, 0x00, 0xff, 0xff], 65535)
, ([0x00, 0xff, 0xff, 0xff], 16777215)
, ([0x7f, 0xff, 0xff, 0xff], 2147483647)
, ([0xff, 0xff, 0xff, 0xff], -1)
, ([0xff, 0xff, 0xff, 0x00], -256)
, ([0xff, 0xff, 0x00, 0x00], -65536)
, ([0xff, 0x00, 0x00, 0x00], -16777216)
, ([0x80, 0x00, 0x00, 0x00], -2147483648)
]
it "can parse 64-bit integers" $
parseCases P.int64
[ ([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01], 1)
, ([0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff], 4294967295)
, ([0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff], 1099511627775)
, ([0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], 281474976710655)
, ([0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], 72057594037927935)
, ([0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], 9223372036854775807)
, ([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], -1)
, ([0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00], -4294967296)
, ([0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00], -1099511627776)
, ([0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], -281474976710656)
, ([0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], -72057594037927936)
, ([0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], -9223372036854775808)
]
it "can parse 64-bit little endian integers" $
parseCases P.int64LE
[ ([0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], 1)
, ([0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00], 4294967295)
, ([0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00], 1099511627775)
, ([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00], 281474976710655)
, ([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00], 72057594037927935)
, ([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f], 9223372036854775807)
, ([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], -1)
, ([0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff], -4294967296)
, ([0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff], -1099511627776)
, ([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff], -281474976710656)
, ([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff], -72057594037927936)
, ([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80], -9223372036854775808)
]
it "can parse doubles" $
parseCases P.double
[ ([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], 0.0)
, ([0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], 1.0)
, ([0x3f, 0xf0, 0x00, 0x00, 0x00, 0x06, 0xdf, 0x38], 1.0000000001)
, ([0x3f, 0xf1, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a], 1.1)
, ([0xbf, 0xf1, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a], -1.1)
, ([0x40, 0x09, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18], 3.141592653589793)
, ([0xbf, 0xf0, 0x00, 0x00, 0x00, 0x06, 0xdf, 0x38], -1.0000000001)
]
it "can parse little endian doubles" $
parseCases P.doubleLE
[ ([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], 0.0)
, ([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f], 1.0)
, ([0x38, 0xdf, 0x06, 0x00, 0x00, 0x00, 0xf0, 0x3f], 1.0000000001)
, ([0x9a, 0x99, 0x99, 0x99, 0x99, 0x99, 0xf1, 0x3f], 1.1)
, ([0x9a, 0x99, 0x99, 0x99, 0x99, 0x99, 0xf1, 0xbf], -1.1)
, ([0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40], 3.141592653589793)
, ([0x38, 0xdf, 0x06, 0x00, 0x00, 0x00, 0xf0, 0xbf], -1.0000000001)
]
describe "take" $ do
prop "returns the requested number of bytes" $
\n (SomeByteString bs) ->
B.length bs >= n ==>
(B.length <$> P.runParser (P.take n) bs) === Right n
prop "fails when input is too short" $
\n (SomeByteString bs) ->
B.length bs < n ==> isLeft (P.runParser (P.take n) bs)