{-# LANGUAGE CPP, OverloadedStrings, TemplateHaskell #-}
module QC.Combinator where
#if !MIN_VERSION_base(4,8,0)
import Control.Applicative ((<*>), (<$>), (<*), (*>))
#endif
import Data.Maybe (fromJust, isJust)
import Data.Word (Word8)
import QC.Common (Repack, parseBS, repackBS, toLazyBS)
import Test.Tasty (TestTree)
import Test.Tasty.QuickCheck (testProperty)
import Test.QuickCheck
import qualified Data.Attoparsec.ByteString.Char8 as P
import qualified Data.Attoparsec.Combinator as C
import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as B8
import Debug.TraceEmbrace
choice :: NonEmptyList (NonEmptyList Word8) -> Gen Property
choice (NonEmpty xs) = do
let ys = map (B.pack . getNonEmpty) xs
return . forAll (repackBS <$> arbitrary <*> elements ys) $
maybe False (`elem` ys) . parseBS (C.choice (map P.string ys))
count :: Positive (Small Int) -> Repack -> B.ByteString -> Bool
count (Positive (Small n)) rs s =
(length <$> parseBS (C.count n (P.string s)) input) == Just n
where input = repackBS rs (B.concat (replicate (n+1) s))
lookAhead :: NonEmptyList Word8 -> Bool
lookAhead (NonEmpty xs) =
let ys = B.pack xs
withLookAheadThenConsume = (\x y -> (x, y)) <$> C.lookAhead (P.string ys) <*> P.string ys
mr = parseBS withLookAheadThenConsume $ toLazyBS ys
in isJust mr && fst (fromJust mr) == snd (fromJust mr)
match :: Int -> NonNegative Int -> NonNegative Int -> Repack -> Bool
match n (NonNegative x) (NonNegative y) rs =
$(tw "parsed") (parseBS (P.match parser)
($(tw' "repacked") (repackBS rs input))) ==
Just ($(tw' "input") input, n)
where parser = P.skipWhile (=='x') *> P.signed P.decimal <*
P.skipWhile (=='y')
input = B.concat [
B8.replicate x 'x', B8.pack (show n), B8.replicate y 'y'
]
manyPrime :: [Word] -> Repack -> Bool
manyPrime n rs =
$(tw "parsed") (parseBS (P.match parser)
($(tw' "repacked") (repackBS rs input))) ==
Just ($(tw' "input") input, n)
where parser = P.many' (P.decimal <* P.skipSpace)
input = B8.pack (unwords $ fmap show n)
tests :: [TestTree]
tests = [
testProperty "choice" choice
, testProperty "count" count
, testProperty "manyPrime" manyPrime
, testProperty "lookAhead" lookAhead
, testProperty "match" match
]