altsvc-0.1.0.0: tests/Tests.hs
{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
import Data.ByteString (ByteString)
import qualified Data.ByteString as B
import Data.Serialize
import Network.HTTP.AltSvc
import Test.Tasty
import Test.Tasty.HUnit
import Test.Tasty.QuickCheck
arbitraryByteString :: Gen ByteString
arbitraryByteString = B.pack <$> listOf (choose (0,255))
arbitraryToken :: Gen ByteString
arbitraryToken = B.pack <$> listOf1 arbitraryTokenByte
where
arbitraryTokenByte = oneof
[ elements [ 0x21, 0x23, 0x24, 0x25, 0x26, 0x27, 0x2a, 0x2b
, 0x2d, 0x2e, 0x5e, 0x5f, 0x60, 0x7c, 0x7e ]
, choose (0x30, 0x39) -- 0-9
, choose (0x41, 0x5a) -- A-Z
, choose (0x61, 0x7a) -- a-z
]
arbitraryParam :: Gen (ByteString, ByteString)
arbitraryParam = (,) <$> arbitraryToken <*> arbitraryByteString
arbitraryProtocolId :: Gen ByteString
arbitraryProtocolId = B.pack <$> listOf1 (choose (0,255))
instance Arbitrary AltValue where
arbitrary = AltValue
<$> arbitraryProtocolId
<*> arbitraryByteString
<*> choose (0,65535)
<*> listOf arbitraryParam
instance Arbitrary AltSvc where
arbitrary = fmap AltSvc arbitrary
vectors :: [(AltSvc, ByteString)]
vectors =
[ ( AltSvc []
, "clear")
, ( AltSvc [AltValue "h2" "" 8000 []]
, "h2=\":8000\"")
, ( AltSvc [AltValue "h2" "new.example.org" 80 []]
, "h2=\"new.example.org:80\"")
, ( AltSvc [AltValue "w=x:y#z" "" 80 []]
, "w%3Dx%3Ay#z=\":80\"")
, ( AltSvc [AltValue "x%y" "" 80 []]
, "x%25y=\":80\"")
, ( AltSvc [AltValue "h2" "alt.example.com" 8000 [], AltValue "h2" "" 443 []]
, "h2=\"alt.example.com:8000\", h2=\":443\"")
, ( AltSvc [AltValue "h2" "" 443 [("ma", "3600")]]
, "h2=\":443\"; ma=3600")
, ( AltSvc [AltValue "h2" "" 443 [("ma", "2592000"), ("persist", "1")]]
, "h2=\":443\"; ma=2592000; persist=1")
, ( AltSvc [AltValue "clear" "alt.example.com" 8080 []]
, "clear=\"alt.example.com:8080\"")
]
runGetFull :: Get a -> ByteString -> Either String a
runGetFull parse bs = handle (runGetPartial parse bs)
where
handle result = case result of
Fail i _ -> Left i
Partial f -> handle (f B.empty) -- confirm complete
Done a rb
| B.null rb -> Right a -- fully parsed
| otherwise -> Left ("Remaining bytes: " ++ show rb)
main :: IO ()
main = defaultMain $ testGroup "altsvc"
[ localOption (QuickCheckMaxSize 10) $ testGroup "properties"
[ testProperty "AltValue" $ \v ->
runGetFull get (runPut $ put v) === Right (v :: AltValue)
, testProperty "AltSvc" $ \v ->
runGetFull get (runPut $ put v) === Right (v :: AltSvc)
]
, testGroup "vectors" $
let toCase i (v, bs) = testGroup (show i)
[ testCase "getting" $ Right v @=? runGetFull get bs
, testCase "putting" $ bs @=? runPut (put v)
]
in zipWith toCase [(1::Int)..] vectors
]