packages feed

http-media-0.2.0: test/Network/HTTP/Media/Tests.hs

------------------------------------------------------------------------------
module Network.HTTP.Media.Tests (tests) where

------------------------------------------------------------------------------
import Control.Monad                     (replicateM)
import Data.ByteString                   (ByteString)
import Data.ByteString.UTF8              (fromString)
import Data.List                         (intercalate)
import Data.Map                          (empty)
import Data.Maybe                        (isNothing, listToMaybe)
import Data.Word                         (Word16)
import Distribution.TestSuite.QuickCheck
import Test.QuickCheck

------------------------------------------------------------------------------
import Network.HTTP.Media                    hiding (parameters, subType)
import Network.HTTP.Media.MediaType.Gen
import Network.HTTP.Media.MediaType.Internal
import Network.HTTP.Media.Quality


------------------------------------------------------------------------------
tests :: [Test]
tests =
    [ testParse
    , testMatchAccept
    , testMapAccept
    , testMatchContent
    , testMapContent
    , testMatchQuality
    , testMapQuality
    ]


------------------------------------------------------------------------------
testParse :: Test
testParse = testGroup "parseQuality"
    [ testProperty "Without quality" $ do
        media <- medias
        return $
            parseQuality (group media) == Just (map maxQuality media)
    , testProperty "With quality" $ do
        media <- medias >>= mapM (flip fmap (choose (0, 1000)) . Quality)
        return $ parseQuality (group media) == Just media
    ]
  where
    medias = listOf1 genMediaType
    group media = fromString $ intercalate "," (map show media)


------------------------------------------------------------------------------
testMatchAccept :: Test
testMatchAccept = testMatch "Accept" matchAccept qToBS


------------------------------------------------------------------------------
testMapAccept :: Test
testMapAccept = testMap "Accept" mapAccept qToBS


------------------------------------------------------------------------------
testMatchContent :: Test
testMatchContent = testGroup "matchContent"
    [ testProperty "Most specific" $ do
        media <- genConcreteMediaType
        let client = toBS
                [ MediaType "*" "*" empty
                , media { subType = "*" }
                , media { parameters = empty }
                , media
                ]
        return $ matchAccept [media] client == Just media
    , testProperty "Nothing" $ do
        (server, client) <- genServerAndClient
        let client' = filter (not . flip any server . matches) client
        return . isNothing $ matchAccept server (toBS client')
    , testProperty "Left biased" $ do
        server <- genServer
        return $ matchAccept server (toBS server) == Just (head server)
    , testProperty "Against */*" $ do
        server <- genServer
        let stars = "*/*" :: ByteString
        return $ matchAccept server (toBS [stars]) == Just (head server)
    , testProperty "Against type/*" $ do
        server <- genServer
        let client = toBS [subStarOf $ head server]
        return $ matchAccept server client == Just (head server)
    ]


------------------------------------------------------------------------------
testMapContent :: Test
testMapContent = testGroup "mapContent"
    [ testProperty "Matches" $ do
        server <- genServer
        let zipped = zip server server
        return $ mapAccept zipped (toBS server) == listToMaybe server
    , testProperty "Nothing" $ do
        server <- genServer
        client <- listOf1 $ genDiffMediaTypesWith genConcreteMediaType server
        let zipped = zip server $ repeat ()
        return . isNothing $ mapAccept zipped (toBS client)
    ]


------------------------------------------------------------------------------
testMatchQuality :: Test
testMatchQuality = testMatch "Quality" matchQuality id


------------------------------------------------------------------------------
testMapQuality :: Test
testMapQuality = testMap "Quality" mapQuality id


------------------------------------------------------------------------------
testMatch
    :: String
    -> ([MediaType] -> a -> Maybe MediaType)
    -> ([Quality MediaType] -> a)
    -> Test
testMatch name match qToI = testGroup ("match" ++ name)
    [ testProperty "Highest quality" $ do
        server <- genServer
        qs     <- replicateM (length server) $ choose (1, 1000)
        let client = zipWith Quality server qs
            qmax v q = if qualityValue q > qualityValue v then q else v
        return $ match server (qToI client) ==
            Just (qualityData $ foldr1 qmax client)
    , testProperty "Most specific" $ do
        media <- genConcreteMediaType
        let client = qToI $ map maxQuality
                [ MediaType "*" "*" empty
                , media { subType = "*" }
                , media { parameters = empty }
                , media
                ]
        return $ match [media] client == Just media
    , testProperty "Nothing" $ do
        server <- genServer
        client <- listOf1 $ genDiffMediaTypesWith genConcreteMediaType server
        let client' = filter (not . flip any server . matches) client
        return . isNothing $ match server
            (qToI $ map maxQuality client')
    , testProperty "Never chooses q=0" $ do
        server <- genServer
        return . isNothing $
            match server (qToI $ map minQuality server)
    , testProperty "Left biased" $ do
        server <- genServer
        let client = qToI $ map maxQuality server
        return $ match server client == Just (head server)
    , testProperty "Against */*" $ do
        server <- genServer
        let stars = "*/*" :: MediaType
        return $ match server (qToI [maxQuality stars]) ==
            Just (head server)
    , testProperty "Against type/*" $ do
        server <- genServer
        let client = qToI [maxQuality (subStarOf $ head server)]
        return $ match server client == Just (head server)
    ]


------------------------------------------------------------------------------
testMap
    :: String
    -> ([(MediaType, MediaType)] -> a -> Maybe MediaType)
    -> ([Quality MediaType] -> a)
    -> Test
testMap name mapf qToI = testGroup ("map" ++ name)
    [ testProperty "Matches" $ do
        server <- genServer
        qs     <- replicateM (length server) $ choose (1, 1000 :: Word16)
        let client = zipWith Quality server qs
            qmax q v = if qualityValue q >= qualityValue v then q else v
            zipped = zip server server
        return $ mapf zipped (qToI client) ==
            Just (qualityData $ foldr1 qmax client)
    , testProperty "Nothing" $ do
        (server, client) <- genServerAndClient
        let zipped = zip server $ repeat "*/*"
        return . isNothing $ mapf zipped (qToI $ map maxQuality client)
    ]


------------------------------------------------------------------------------
genServer :: Gen [MediaType]
genServer = listOf1 genConcreteMediaType


------------------------------------------------------------------------------
genServerAndClient :: Gen ([MediaType], [MediaType])
genServerAndClient = do
    server <- genServer
    client <- listOf1 $ genDiffMediaTypesWith genConcreteMediaType server
    return (server, client)


------------------------------------------------------------------------------
toBS :: Accept a => [a] -> ByteString
toBS = fromString . intercalate "," . map showAccept


------------------------------------------------------------------------------
qToBS :: Accept a => [Quality a] -> ByteString
qToBS = fromString . intercalate "," . map show