websockets-0.11.2.0: tests/haskell/Network/WebSockets/Mask/Tests.hs
--------------------------------------------------------------------------------
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE OverloadedStrings #-}
module Network.WebSockets.Mask.Tests
( tests
) where
--------------------------------------------------------------------------------
import qualified Data.Binary.Get as Get
import Data.Bits (xor)
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as BL
import Network.WebSockets.Hybi13.Mask
import Test.Framework (Test, testGroup)
import Test.Framework.Providers.QuickCheck2 (testProperty)
import Test.QuickCheck (Arbitrary (..), (===))
import qualified Test.QuickCheck as QC
--------------------------------------------------------------------------------
import Network.WebSockets.Tests.Util
tests :: Test
tests = testGroup "Network.WebSockets.Masks.Tests"
[ testProperty "correct fast masking" testMasking ]
maskPayload' :: Maybe B.ByteString -> BL.ByteString -> BL.ByteString
maskPayload' Nothing = id
maskPayload' (Just mask) = snd . BL.mapAccumL f (cycle $ B.unpack mask)
where
f [] !c = ([], c)
f (m:ms) !c = (ms, m `xor` c)
newtype AMask = AMask B.ByteString deriving (Show)
instance Arbitrary AMask where
arbitrary = do
c1 <- arbitrary
c2 <- arbitrary
c3 <- arbitrary
c4 <- arbitrary
return (AMask (B.pack [c1,c2,c3,c4]))
newtype APkt = APkt BL.ByteString deriving (Show)
instance Arbitrary APkt where
arbitrary = do
b1 <- arbitraryByteString
b2 <- arbitraryByteString
return $ APkt (b1 `BL.append` b2) -- Just for sure to test correctly different alignments
shrink (APkt bs) =
map APkt [ BL.append a b | (a, b) <- zip (BL.inits bs) (tail $ BL.tails bs) ]
testMasking :: QC.Property
testMasking =
QC.forAllShrink QC.arbitrary QC.shrink $ \(AMask mask, APkt pkt) ->
let wmask = Get.runGet parseMask (BL.fromStrict mask)
in maskPayload' (Just mask) pkt === maskPayload (Just wmask) pkt