git.iko.soy/typeable/attoparsec
on master help sign in
Basic test support
commit2e0691085b33c4e0aed6a1aa70151175ef59fd27 authorBryan O'Sullivan <bos@serpentine.com> dateFri 16 Jan 2009, 15:03 (18 years ago) parent5c15893
5 files changed+152−5
.hgignore+2 tests/Makefile+9−3 tests/QC.hs+63 tests/QCSupport.hs+76 tests/TestFastSet.hs+2−2
.hgignore+2
@@ -8,3 +8,5 @@ syntax: glob
88*.orig
99\#*
1010.\#*
11+tests/*.out
12+*.exe
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+63
@@ -0,0 +1,63 @@
1+module Main (main) where
2+
3+import Control.Applicative
4+import Data.Attoparsec
5+import Data.List (isInfixOf)
6+import Data.Maybe (isJust)
7+import Data.Word (Word8)
8+import Control.Monad
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+--p :: Testable a => a -> Int -> IO ()
42+p prop count = limCheck count prop
43+
44+main = do
45+ args <- getArgs
46+ let n = case args of
47+ [] -> 100
48+ [k] -> read k
49+ _ -> error "too many arguments"
50+ forM_ tests $ \(name,prop) -> do
51+ putStr name
52+ putStr (replicate (40 - length name) ' ')
53+ hFlush stdout
54+ prop n
55+
56+tests = [
57+ ("nonEmptyList", p prop_nonEmptyList),
58+ ("nonEmptyBS", p prop_nonEmptyBS),
59+ ("nonEmptyLBS", p prop_nonEmptyLBS),
60+ ("word8", p prop_word8),
61+ ("notWord8", p prop_notWord8),
62+ ("anyWord8", p prop_anyWord8)
63+ ]
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