{-# LANGUAGE
NamedFieldPuns
, OverloadedStrings
, ScopedTypeVariables
#-}
module Main where
import Path (parseAbsDir, parseAbsFile, Path, Abs, Dir, File)
import Path.Extended (Location (..), QueryParam, locationAbsDirParser, locationAbsFileParser)
import qualified Data.Text as T
import Data.Monoid ((<>))
import Data.Attoparsec.Text (parseOnly)
import Control.Exception (SomeException)
import Control.Monad (replicateM)
import Test.Tasty (defaultMain, testGroup)
import qualified Test.Tasty.QuickCheck as QC
import Test.QuickCheck (Arbitrary (..), suchThat)
import Test.QuickCheck.Gen (Gen, choose, elements, listOf)
import Test.QuickCheck.Instances ()
newtype ArbitraryLocationAbsDir = ArbitraryLocationAbsDir
{ getArbitraryLocationAbsDir :: Location Abs Dir
} deriving (Eq, Show)
instance Arbitrary ArbitraryLocationAbsDir where
arbitrary = do
locPath <- arbitraryPath
locQueryParams <- arbitraryQueryParams
locFragment <- arbitraryFragment
pure $ ArbitraryLocationAbsDir Location
{ locParentJumps = 0
, locPath
, locFileExt = Nothing
, locQueryParams
, locFragment
}
where
arbitraryFragment :: Gen (Maybe String)
arbitraryFragment = do
build <- arbitrary
if not build
then pure Nothing
else
fmap Just $ listOf (elements (['A'..'Z'] <> ['a'..'z'])) `suchThat` (not . null)
arbitraryQueryParams :: Gen [QueryParam]
arbitraryQueryParams = do
build <- arbitrary
if not build
then pure []
else do
let arbitraryVal :: Gen String
arbitraryVal =
listOf (elements (['A'..'Z'] <> ['a'..'z'])) `suchThat` (not . null)
n <- choose (1,4)
let arbitraryKV :: Gen QueryParam
arbitraryKV = do
k <- arbitraryVal
buildVal <- arbitrary
mV <-
if buildVal
then Just <$> arbitraryVal
else pure Nothing
pure (k,mV)
replicateM n arbitraryKV
arbitraryPath :: Gen (Path Abs Dir)
arbitraryPath = do
n <- choose (0,5)
xs <- replicateM n arbitraryChunk
pure $ case parseAbsDir ( case xs of
[] -> "/"
_ -> T.unpack ("/" <> T.intercalate "/" xs <> "/")
) of
Left (e :: SomeException) ->
error $ "Can't parse abs dir! " <> show e
Right path -> path
arbitraryChunk :: Gen T.Text
arbitraryChunk = fmap T.pack $
listOf (elements (['A'..'Z'] <> ['a'..'z'])) `suchThat` (not . null)
newtype ArbitraryLocationAbsFile = ArbitraryLocationAbsFile
{ getArbitraryLocationAbsFile :: Location Abs File
} deriving (Eq, Show)
instance Arbitrary ArbitraryLocationAbsFile where
arbitrary = do
locPath <- arbitraryPath
locFileExt <- arbitraryFileExt
locQueryParams <- arbitraryQueryParams
locFragment <- arbitraryFragment
pure $ ArbitraryLocationAbsFile Location
{ locParentJumps = 0
, locPath
, locFileExt
, locQueryParams
, locFragment
}
where
arbitraryFragment :: Gen (Maybe String)
arbitraryFragment = do
build <- arbitrary
if not build
then pure Nothing
else
fmap Just $ listOf (elements (['A'..'Z'] <> ['a'..'z'])) `suchThat` (not . null)
arbitraryQueryParams :: Gen [QueryParam]
arbitraryQueryParams = do
build <- arbitrary
if not build
then pure []
else do
let arbitraryVal :: Gen String
arbitraryVal =
listOf (elements (['A'..'Z'] <> ['a'..'z'])) `suchThat` (not . null)
n <- choose (1,4)
let arbitraryKV :: Gen QueryParam
arbitraryKV = do
k <- arbitraryVal
buildVal <- arbitrary
mV <-
if buildVal
then Just <$> arbitraryVal
else pure Nothing
pure (k,mV)
replicateM n arbitraryKV
arbitraryPath :: Gen (Path Abs File)
arbitraryPath = do
n <- choose (1,5)
xs <- replicateM n arbitraryChunk
pure $ case parseAbsFile ( case xs of
[] -> "/"
_ -> T.unpack ("/" <> T.intercalate "/" xs)
) of
Left (e :: SomeException) ->
error $ "Can't parse abs file! " <> show e
Right path -> path
arbitraryFileExt :: Gen (Maybe String)
arbitraryFileExt = do
build <- arbitrary
if not build
then pure Nothing
else
Just <$> listOf (elements (['A'..'Z'] <> ['a'..'z'])) `suchThat` (not . null)
arbitraryChunk :: Gen T.Text
arbitraryChunk = fmap T.pack $
listOf (elements (['A'..'Z'] <> ['a'..'z'])) `suchThat` (not . null)
printParseIsoAbsDir :: ArbitraryLocationAbsDir -> Bool
printParseIsoAbsDir (ArbitraryLocationAbsDir loc) =
Right loc == parseOnly locationAbsDirParser (T.pack (show loc))
printParseIsoAbsFile :: ArbitraryLocationAbsFile -> Bool
printParseIsoAbsFile (ArbitraryLocationAbsFile loc) =
Right loc == parseOnly locationAbsFileParser (T.pack (show loc))
main :: IO ()
main = defaultMain $
testGroup "Path.Extended"
[ QC.testProperty "Print / Parse AbsDir Iso" printParseIsoAbsDir
, QC.testProperty "Print / Parse AbsFile Iso" printParseIsoAbsFile
]