git.iko.soy/typeable/attoparsec
on master help sign in
Add an initial combinator test
commit9cb63cd65cac211f7d36665dc5075f8607ccb679 authorBryan O'Sullivan <bos@serpentine.com> dateWed 7 May 2014, 15:30 (12 years ago) parentc045c10
6 files changed+87−52
attoparsec.cabal+1 tests/QC.hs+2 tests/QC/ByteString.hs+23−29 tests/QC/Combinator.hs+22 tests/QC/Common.hs+21−1 tests/QC/Text.hs+18−22
attoparsec.cabal+1
@@ -73,6 +73,7 @@ test-suite tests
7373 hs-source-dirs: tests
7474 main-is: QC.hs
7575 other-modules: QC.ByteString
76+ QC.Combinator
7677 QC.Common
7778 QC.Text
7879
tests/QC.hs+2
@@ -2,6 +2,7 @@
22module Main (main) where
33
44import qualified QC.ByteString as ByteString
5+import qualified QC.Combinator as Combinator
56import qualified QC.Text as Text
67import Test.Framework (defaultMain, testGroup)
78
@@ -9,5 +10,6 @@ main = defaultMain tests
910
1011tests = [
1112 testGroup "bs" ByteString.tests
13+ , testGroup "combinator" Combinator.tests
1214 , testGroup "text" Text.tests
1315 ]
tests/QC/ByteString.hs+23−29
@@ -6,7 +6,7 @@ import Data.Char (chr, ord)
66import Data.Int (Int64)
77import Data.Word (Word8)
88import Prelude hiding (take, takeWhile)
9−import QC.Common ()
9+import QC.Common (parseBS, toStrictBS)
1010import Test.Framework (Test)
1111import Test.Framework.Providers.QuickCheck2 (testProperty)
1212import Test.QuickCheck
@@ -19,22 +19,19 @@ import qualified Data.ByteString.Lazy.Char8 as L8
1919
2020-- Basic byte-level combinators.
2121
22−maybeP :: PL.Parser r -> L.ByteString -> Maybe r
23−maybeP p = PL.maybeResult . PL.parse p
24−
2522satisfy :: Word8 -> L.ByteString -> Bool
26−satisfy w s = maybeP (P.satisfy (<=w)) (L.cons w s) == Just w
23+satisfy w s = parseBS (P.satisfy (<=w)) (L.cons w s) == Just w
2724
2825satisfyWith :: Char -> L.ByteString -> Bool
29−satisfyWith c s = maybeP (P.satisfyWith (chr . fromIntegral) (<=c))
26+satisfyWith c s = parseBS (P.satisfyWith (chr . fromIntegral) (<=c))
3027 (L.cons (fromIntegral (ord c)) s) == Just c
3128
3229word8 :: Word8 -> L.ByteString -> Bool
33−word8 w s = maybeP (P.word8 w) (L.cons w s) == Just w
30+word8 w s = parseBS (P.word8 w) (L.cons w s) == Just w
3431
3532skip :: Word8 -> L.ByteString -> Bool
3633skip w s =
37− case (maybeP (P.skip (<w)) s, L.uncons s) of
34+ case (parseBS (P.skip (<w)) s, L.uncons s) of
3835 (Nothing, mcs) -> maybe True (not . it) mcs
3936 (Just _, mcs) -> maybe False it mcs
4037 where it cs = fst cs < w
@@ -43,10 +40,10 @@ anyWord8 :: L.ByteString -> Bool
4340anyWord8 s
4441 | L.null s = p == Nothing
4542 | otherwise = p == Just (L.head s)
46− where p = maybeP P.anyWord8 s
43+ where p = parseBS P.anyWord8 s
4744
4845notWord8 :: Word8 -> NonEmptyList Word8 -> Bool
49−notWord8 w (NonEmpty s) = maybeP (P.notWord8 w) bs == if v == w
46+notWord8 w (NonEmpty s) = parseBS (P.notWord8 w) bs == if v == w
5047 then Nothing
5148 else Just v
5249 where v = L.head bs
@@ -56,17 +53,14 @@ peekWord8 :: L.ByteString -> Bool
5653peekWord8 s
5754 | L.null s = p == Just (Nothing, s)
5855 | otherwise = p == Just (Just (L.head s), s)
59− where p = maybeP ((,) <$> P.peekWord8 <*> P.takeLazyByteString) s
56+ where p = parseBS ((,) <$> P.peekWord8 <*> P.takeLazyByteString) s
6057
6158peekWord8' :: L.ByteString -> Bool
62−peekWord8' s = maybeP P.peekWord8' s == (fst <$> L.uncons s)
59+peekWord8' s = parseBS P.peekWord8' s == (fst <$> L.uncons s)
6360
6461string :: L.ByteString -> L.ByteString -> Bool
65−string s t = maybeP (P.string s') (s `L.append` t) == Just s'
66− where s' = toStrict s
67−
68−toStrict :: L.ByteString -> B.ByteString
69−toStrict = B.concat . L.toChunks
62+string s t = parseBS (P.string s') (s `L.append` t) == Just s'
63+ where s' = toStrictBS s
7064
7165skipWhile :: Word8 -> L.ByteString -> Bool
7266skipWhile w s =
@@ -77,7 +71,7 @@ skipWhile w s =
7771
7872takeCount :: Positive Int -> L.ByteString -> Bool
7973takeCount (Positive k) s =
80− case maybeP (P.take k) s of
74+ case parseBS (P.take k) s of
8175 Nothing -> fromIntegral k > L.length s
8276 Just _s -> fromIntegral k <= L.length s
8377
@@ -85,51 +79,51 @@ takeWhile :: Word8 -> L.ByteString -> Bool
8579takeWhile w s =
8680 let (h,t) = L.span (==w) s
8781 in case PL.parse (P.takeWhile (==w)) s of
88− PL.Done t' h' -> t == t' && toStrict h == h'
82+ PL.Done t' h' -> t == t' && toStrictBS h == h'
8983 _ -> False
9084
9185take :: Int -> L.ByteString -> Bool
92−take n s = maybe (L.length s < fromIntegral n) (== B.take n (toStrict s)) $
93− maybeP (P.take n) s
86+take n s = maybe (L.length s < fromIntegral n) (== B.take n (toStrictBS s)) $
87+ parseBS (P.take n) s
9488
9589takeByteString :: L.ByteString -> Bool
96−takeByteString s = maybe False (== toStrict s) . maybeP P.takeByteString $ s
90+takeByteString s = maybe False (== toStrictBS s) . parseBS P.takeByteString $ s
9791
9892takeLazyByteString :: L.ByteString -> Bool
99−takeLazyByteString s = maybe False (== s) . maybeP P.takeLazyByteString $ s
93+takeLazyByteString s = maybe False (== s) . parseBS P.takeLazyByteString $ s
10094
10195takeWhile1 :: Word8 -> L.ByteString -> Bool
10296takeWhile1 w s =
10397 let s' = L.cons w s
10498 (h,t) = L.span (<=w) s'
10599 in case PL.parse (P.takeWhile1 (<=w)) s' of
106− PL.Done t' h' -> t == t' && toStrict h == h'
100+ PL.Done t' h' -> t == t' && toStrictBS h == h'
107101 _ -> False
108102
109103takeTill :: Word8 -> L.ByteString -> Bool
110104takeTill w s =
111105 let (h,t) = L.break (==w) s
112106 in case PL.parse (P.takeTill (==w)) s of
113− PL.Done t' h' -> t == t' && toStrict h == h'
107+ PL.Done t' h' -> t == t' && toStrictBS h == h'
114108 _ -> False
115109
116110takeWhile1_empty :: Bool
117−takeWhile1_empty = maybeP (P.takeWhile1 undefined) L.empty == Nothing
111+takeWhile1_empty = parseBS (P.takeWhile1 undefined) L.empty == Nothing
118112
119113endOfInput :: L.ByteString -> Bool
120−endOfInput s = maybeP P.endOfInput s == if L.null s
114+endOfInput s = parseBS P.endOfInput s == if L.null s
121115 then Just ()
122116 else Nothing
123117
124118endOfLine :: L.ByteString -> Bool
125119endOfLine s =
126− case (maybeP P8.endOfLine s, L8.uncons s) of
120+ case (parseBS P8.endOfLine s, L8.uncons s) of
127121 (Nothing, mcs) -> maybe True (not . eol) mcs
128122 (Just _, mcs) -> maybe False eol mcs
129123 where eol (c,s') = c == '\n' || (c, fst <$> L8.uncons s') == ('\r', Just '\n')
130124
131125scan :: L.ByteString -> Positive Int64 -> Bool
132−scan s (Positive k) = maybeP p s == (Just $ toStrict $ L.take k s)
126+scan s (Positive k) = parseBS p s == (Just $ toStrictBS $ L.take k s)
133127 where p = P.scan k $ \ n _ ->
134128 if n > 0 then let !n' = n - 1 in Just n' else Nothing
135129
tests/QC/Combinator.hsnew file+22
@@ -0,0 +1,22 @@
1+module QC.Combinator where
2+
3+import Control.Applicative
4+import Data.Word (Word8)
5+import QC.Common (parseBS, toLazyBS)
6+import Test.Framework (Test)
7+import Test.Framework.Providers.QuickCheck2 (testProperty)
8+import Test.QuickCheck
9+import qualified Data.Attoparsec.ByteString.Char8 as P
10+import qualified Data.Attoparsec.Combinator as C
11+import qualified Data.ByteString as B
12+
13+choice :: NonEmptyList (NonEmptyList Word8) -> Gen Property
14+choice (NonEmpty xs) = do
15+ let ys = map (B.pack . getNonEmpty) xs
16+ return . forAll (toLazyBS <$> elements ys) $
17+ maybe False (`elem` ys) . parseBS (C.choice (map P.string ys))
18+
19+tests :: [Test]
20+tests = [
21+ testProperty "choice" choice
22+ ]
tests/QC/Common.hs+21−1
@@ -1,5 +1,11 @@
11{-# OPTIONS_GHC -fno-warn-orphans #-}
2−module QC.Common () where
2+module QC.Common
3+ (
4+ parseBS
5+ , parseT
6+ , toLazyBS
7+ , toStrictBS
8+ ) where
39
410import Control.Applicative ((<$>))
511import Test.QuickCheck
@@ -7,6 +13,20 @@ import qualified Data.ByteString as B
713import qualified Data.ByteString.Lazy as BL
814import qualified Data.Text as T
915import qualified Data.Text.Lazy as TL
16+import qualified Data.Attoparsec.ByteString.Lazy as BL
17+import qualified Data.Attoparsec.Text.Lazy as TL
18+
19+parseBS :: BL.Parser r -> BL.ByteString -> Maybe r
20+parseBS p = BL.maybeResult . BL.parse p
21+
22+parseT :: TL.Parser r -> TL.Text -> Maybe r
23+parseT p = TL.maybeResult . TL.parse p
24+
25+toStrictBS :: BL.ByteString -> B.ByteString
26+toStrictBS = B.concat . BL.toChunks
27+
28+toLazyBS :: B.ByteString -> BL.ByteString
29+toLazyBS = BL.fromChunks . (:[])
1030
1131instance Arbitrary B.ByteString where
1232 arbitrary = B.pack <$> arbitrary
tests/QC/Text.hs+18−22
@@ -3,10 +3,9 @@
33module QC.Text (tests) where
44
55import Control.Applicative ((<$>), (<*>))
6−import Data.Attoparsec.Text (Parser)
76import Data.Int (Int64)
87import Prelude hiding (take, takeWhile)
9−import QC.Common ()
8+import QC.Common (parseT)
109import Test.Framework (Test)
1110import Test.Framework.Providers.QuickCheck2 (testProperty)
1211import Test.QuickCheck
@@ -18,21 +17,18 @@ import qualified Data.Text.Lazy as L
1817
1918-- Basic byte-level combinators.
2019
21−maybeP :: Parser r -> L.Text -> Maybe r
22−maybeP p = PL.maybeResult . PL.parse p
23−
2420satisfy :: Char -> L.Text -> Bool
25−satisfy w s = maybeP (P.satisfy (<=w)) (L.cons w s) == Just w
21+satisfy w s = parseT (P.satisfy (<=w)) (L.cons w s) == Just w
2622
2723satisfyWith :: Char -> L.Text -> Bool
28−satisfyWith c s = maybeP (P.satisfyWith id (<=c)) (L.cons c s) == Just c
24+satisfyWith c s = parseT (P.satisfyWith id (<=c)) (L.cons c s) == Just c
2925
3026char :: Char -> L.Text -> Bool
31−char w s = maybeP (P.char w) (L.cons w s) == Just w
27+char w s = parseT (P.char w) (L.cons w s) == Just w
3228
3329skip :: Char -> L.Text -> Bool
3430skip w s =
35− case (maybeP (P.skip (<w)) s, L.uncons s) of
31+ case (parseT (P.skip (<w)) s, L.uncons s) of
3632 (Nothing, mcs) -> maybe True (not . it) mcs
3733 (Just _, mcs) -> maybe False it mcs
3834 where it cs = fst cs < w
@@ -41,10 +37,10 @@ anyChar :: L.Text -> Bool
4137anyChar s
4238 | L.null s = p == Nothing
4339 | otherwise = p == Just (L.head s)
44− where p = maybeP P.anyChar s
40+ where p = parseT P.anyChar s
4541
4642notChar :: Char -> NonEmptyList Char -> Bool
47−notChar w (NonEmpty s) = maybeP (P.notChar w) bs == if v == w
43+notChar w (NonEmpty s) = parseT (P.notChar w) bs == if v == w
4844 then Nothing
4945 else Just v
5046 where v = L.head bs
@@ -54,13 +50,13 @@ peekChar :: L.Text -> Bool
5450peekChar s
5551 | L.null s = p == Just (Nothing, s)
5652 | otherwise = p == Just (Just (L.head s), s)
57− where p = maybeP ((,) <$> P.peekChar <*> P.takeLazyText) s
53+ where p = parseT ((,) <$> P.peekChar <*> P.takeLazyText) s
5854
5955peekChar' :: L.Text -> Bool
60−peekChar' s = maybeP P.peekChar' s == (fst <$> L.uncons s)
56+peekChar' s = parseT P.peekChar' s == (fst <$> L.uncons s)
6157
6258string :: L.Text -> L.Text -> Bool
63−string s t = maybeP (P.string s') (s `L.append` t) == Just s'
59+string s t = parseT (P.string s') (s `L.append` t) == Just s'
6460 where s' = toStrict s
6561
6662stringCI :: T.Text -> Bool
@@ -89,17 +85,17 @@ skipWhile w s =
8985
9086take :: Int -> L.Text -> Bool
9187take n s = maybe (L.length s < fromIntegral n) (== T.take n (toStrict s)) $
92− maybeP (P.take n) s
88+ parseT (P.take n) s
9389
9490takeText :: L.Text -> Bool
95−takeText s = maybe False (== toStrict s) . maybeP P.takeText $ s
91+takeText s = maybe False (== toStrict s) . parseT P.takeText $ s
9692
9793takeLazyText :: L.Text -> Bool
98−takeLazyText s = maybe False (== s) . maybeP P.takeLazyText $ s
94+takeLazyText s = maybe False (== s) . parseT P.takeLazyText $ s
9995
10096takeCount :: Positive Int -> L.Text -> Bool
10197takeCount (Positive k) s =
102− case maybeP (P.take k) s of
98+ case parseT (P.take k) s of
10399 Nothing -> fromIntegral k > L.length s
104100 Just _s -> fromIntegral k <= L.length s
105101
@@ -126,22 +122,22 @@ takeTill w s =
126122 _ -> False
127123
128124takeWhile1_empty :: Bool
129−takeWhile1_empty = maybeP (P.takeWhile1 undefined) L.empty == Nothing
125+takeWhile1_empty = parseT (P.takeWhile1 undefined) L.empty == Nothing
130126
131127endOfInput :: L.Text -> Bool
132−endOfInput s = maybeP P.endOfInput s == if L.null s
128+endOfInput s = parseT P.endOfInput s == if L.null s
133129 then Just ()
134130 else Nothing
135131
136132endOfLine :: L.Text -> Bool
137133endOfLine s =
138− case (maybeP P.endOfLine s, L.uncons s) of
134+ case (parseT P.endOfLine s, L.uncons s) of
139135 (Nothing, mcs) -> maybe True (not . eol) mcs
140136 (Just _, mcs) -> maybe False eol mcs
141137 where eol (c,s') = c == '\n' || (c, fst <$> L.uncons s') == ('\r', Just '\n')
142138
143139scan :: L.Text -> Positive Int64 -> Bool
144−scan s (Positive k) = maybeP p s == (Just $ toStrict $ L.take k s)
140+scan s (Positive k) = parseT p s == (Just $ toStrict $ L.take k s)
145141 where p = P.scan k $ \ n _ ->
146142 if n > 0 then let !n' = n - 1 in Just n' else Nothing
147143