git.iko.soy/typeable/attoparsec
on master help sign in
Merge
commit25871b67b7b7b2920c63b31071865e6ac4b69ffa authorBryan O'Sullivan <bos@serpentine.com> dateSat 27 Feb 2010, 12:16 (17 years ago) parent87cc34fab476d2
5 files changed+200−5
Data/Attoparsec.hs+1 tests/Makefile+9−3 tests/QC.hs+112 tests/QCSupport.hs+76 tests/TestFastSet.hs+2−2
Data/Attoparsec.hs+1
@@ -43,6 +43,7 @@ module Data.Attoparsec
4343 , I.string
4444 , I.skipWhile
4545 , I.stringTransform
46+ , I.take
4647 , I.takeTill
4748 , I.takeWhile
4849 , I.takeWhile1
tests/Makefile+9−3
@@ -1,5 +1,11 @@
1−tests: TestFastSet.out
1+all: TestFastSet.out QC.out
22
3−%.out: %.hs
4− runghc $< > $<.tmp
3+%.out: %.exe
4+ ./$< | tee $<.tmp
55 mv $<.tmp $@
6+
7+%.exe: %.hs
8+ ghc -O -fno-warn-orphans --make -o $@ $<
9+
10+clean:
11+ -rm -f *.hi *.o *.exe *.out
tests/QC.hsnew file+112
@@ -0,0 +1,112 @@
1+module Main (main) where
2+
3+import Control.Applicative
4+import Data.Attoparsec as P
5+import Data.List (isInfixOf)
6+import Data.Maybe (isJust)
7+import Data.Word (Word8)
8+import Control.Monad (forM_)
9+import Debug.Trace
10+import System.IO
11+import Test.QuickCheck
12+import qualified Data.ByteString as S
13+import qualified Data.ByteString.Lazy as L
14+import System.Environment
15+import QCSupport
16+
17+-- Make sure that structures whose types claim they are non-empty
18+-- really are.
19+
20+prop_nonEmptyList l = length (nonEmpty l) > 0
21+ where types = l :: NonEmpty [Int]
22+prop_nonEmptyBS l = S.length (nonEmpty l) > 0
23+prop_nonEmptyLBS l = L.length (nonEmpty l) > 0
24+
25+-- Naming.
26+
27+prop_label (NonEmpty s) = case parse (anyWord8 <?> s) L.empty of
28+ (_, Left err) -> s `isInfixOf` err
29+ _ -> False
30+
31+-- Basic byte-level combinators.
32+
33+prop_word8 (NonEmpty s) = maybeP (word8 w) s == Just w
34+ where w = L.head s
35+
36+prop_anyWord8 (NonEmpty s) = isJust $ maybeP anyWord8 s
37+
38+prop_notWord8 (w, NonEmpty s) = v /= w ==> maybeP (notWord8 w) s == Just v
39+ where v = L.head s
40+
41+prop_string s = maybeP (string s) s == Just s
42+
43+prop_skipWhile (w,s) =
44+ let (h,t) = L.span (==w) s
45+ in case parse (skipWhile (==w)) s of
46+ (t',Right ()) -> t == t'
47+ _ -> False
48+
49+prop_takeCount (k,s) =
50+ k >= 0 ==>
51+ case maybeP (takeCount k) s of
52+ Nothing -> j > L.length s
53+ Just s' -> j <= L.length s
54+ where j = fromIntegral k
55+
56+prop_takeWhile (w,s) =
57+ let (h,t) = L.span (==w) s
58+ in case parse (P.takeWhile (==w)) s of
59+ (t',Right h') -> t == t' && h == h'
60+ _ -> False
61+
62+prop_takeWhile1 (w, NonEmpty s) =
63+ let (h,t) = L.span (==w) s
64+ in case parse (P.takeWhile (==w)) s of
65+ (t',Right h') -> t == t' && h == h'
66+ _ -> False
67+
68+prop_takeTill (w, s) =
69+ let (h,t) = L.break (==w) s
70+ in case parse (P.takeTill (==w)) s of
71+ (t',Right h') -> t == t' && h == h'
72+ _ -> False
73+
74+prop_takeWhile1_empty = maybeP (P.takeWhile1 undefined) L.empty == Nothing
75+
76+prop_notEmpty_string s = case maybeP (notEmpty (string s)) s of
77+ Nothing -> L.null s
78+ Just s' -> not (L.null s) && s == s'
79+
80+main :: IO ()
81+main = do
82+ args <- getArgs
83+ let n = case args of
84+ [] -> 500
85+ [k] -> read k
86+ _ -> error "too many arguments"
87+ forM_ tests $ \(name,prop) -> do
88+ putStr name
89+ putStr (replicate (40 - length name) ' ')
90+ hFlush stdout
91+ prop n
92+
93+p :: Testable a => a -> Int -> IO ()
94+p prop count = limCheck count prop
95+
96+tests :: [(String, Int -> IO ())]
97+tests = [
98+ ("nonEmptyList", p prop_nonEmptyList),
99+ ("nonEmptyBS", p prop_nonEmptyBS),
100+ ("nonEmptyLBS", p prop_nonEmptyLBS),
101+ ("word8", p prop_word8),
102+ ("notWord8", p prop_notWord8),
103+ ("anyWord8", p prop_anyWord8),
104+ ("string", p prop_string),
105+ ("skipWhile", p prop_skipWhile),
106+ ("takeCount", p prop_takeCount),
107+ ("takeWhile", p prop_takeWhile),
108+ ("takeWhile1", p prop_takeWhile1),
109+ ("takeWhile1_empty", p prop_takeWhile1_empty),
110+ ("takeTill", p prop_takeTill),
111+ ("notEmpty_string", p prop_notEmpty_string)
112+ ]
tests/QCSupport.hsnew file+76
@@ -0,0 +1,76 @@
1+{-# LANGUAGE FlexibleContexts, FlexibleInstances #-}
2+module QCSupport
3+ (
4+ NonEmpty(..)
5+ , limCheck
6+ , maybeP
7+ ) where
8+
9+import Control.Applicative ((<$>))
10+import Data.Attoparsec
11+import Data.Word (Word8)
12+-- import Debug.Trace
13+import System.Random (RandomGen, Random(..))
14+import Test.QuickCheck
15+import qualified Data.ByteString as S
16+import qualified Data.ByteString.Lazy as L
17+
18+integralRandomR :: (Integral a, RandomGen g) => (a,a) -> g -> (a,g)
19+integralRandomR (a,b) g = case randomR (fromIntegral a :: Integer,
20+ fromIntegral b :: Integer) g of
21+ (x,g') -> (fromIntegral x, g')
22+
23+newtype NonEmpty a = NonEmpty { nonEmpty :: a }
24+ deriving (Eq, Ord, Read, Show)
25+
26+instance Functor NonEmpty where
27+ fmap f (NonEmpty a) = NonEmpty (f a)
28+
29+instance Applicative NonEmpty where
30+ NonEmpty f <*> NonEmpty a = NonEmpty (f a)
31+ pure a = NonEmpty a
32+
33+instance Arbitrary a => Arbitrary (NonEmpty [a]) where
34+ arbitrary = NonEmpty <$> sized (\n -> choose (1,n+1) >>= vector)
35+ coarbitrary = coarbitrary . nonEmpty
36+
37+instance Arbitrary S.ByteString where
38+ arbitrary = S.pack <$> arbitrary
39+ coarbitrary = coarbitrary . S.unpack
40+
41+instance Arbitrary (NonEmpty S.ByteString) where
42+ arbitrary = fmap S.pack <$> arbitrary
43+ coarbitrary = coarbitrary . S.unpack . nonEmpty
44+
45+instance Arbitrary L.ByteString where
46+ arbitrary = sized $ \n -> resize (round (sqrt (toEnum n :: Double)))
47+ ((L.fromChunks . map nonEmpty) <$> arbitrary)
48+ coarbitrary = coarbitrary . L.unpack
49+
50+instance Arbitrary (NonEmpty L.ByteString) where
51+ arbitrary = sized $ \n -> resize (round (sqrt (toEnum n :: Double)))
52+ (fmap (L.fromChunks . map nonEmpty) <$> arbitrary)
53+ coarbitrary = coarbitrary . L.unpack . nonEmpty
54+
55+instance Random Word8 where
56+ randomR = integralRandomR
57+ random = randomR (minBound,maxBound)
58+
59+instance Arbitrary Word8 where
60+ arbitrary = choose (minBound, maxBound)
61+ coarbitrary _ = variant 0
62+
63+instance Arbitrary Char where
64+ arbitrary = choose (minBound, maxBound)
65+ coarbitrary _ = variant 0
66+
67+maybeP :: Parser a -> L.ByteString -> Maybe a
68+maybeP p s = case parse p s of
69+ (_, Left _err) -> Nothing
70+ (_, Right a) -> Just a
71+
72+limCheck :: Testable a => Int -> a -> IO ()
73+limCheck limit = check defaultConfig {
74+ configMaxTest = limit
75+ , configEvery = \_ _ -> ""
76+ }
tests/TestFastSet.hs+2−2
@@ -1,7 +1,7 @@
1−module TestFastSet where
1+module Main (main) where
22
33import Data.Word (Word8)
4−import qualified Data.ParserCombinators.Attoparsec.FastSet as F
4+import qualified Data.Attoparsec.FastSet as F
55import System.Random (Random(..), RandomGen)
66import Test.QuickCheck
77