snap-core-1.0.2.0: test/Snap/Internal/Parsing/Tests.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
------------------------------------------------------------------------------
module Snap.Internal.Parsing.Tests ( tests ) where
------------------------------------------------------------------------------
import Control.Applicative (many)
import Data.Attoparsec.ByteString.Char8 (IResult (..), char, string, (<?>))
import qualified Data.ByteString.Char8 as S (concat)
import qualified Data.Map as Map (fromList)
import Data.Word (Word8)
import Snap.Internal.Http.Types (Cookie (Cookie, cookieDomain, cookieExpires, cookieHttpOnly, cookieName, cookiePath, cookieSecure, cookieValue))
import Snap.Internal.Parsing (crlf, finish, fullyParse, fullyParse', pAvPairs, pHeaders, pQuotedString, parseCookie, parseToCompletion, parseUrlEncoded, unsafeFromHex, unsafeFromNat, pTokens)
import Snap.Test.Common (expectExceptionH)
import System.Random (Random (random, randomR))
import Test.Framework (Test)
import Test.Framework.Providers.HUnit (testCase)
import Test.HUnit (assertEqual)
import Test.QuickCheck (Arbitrary (arbitrary), choose)
------------------------------------------------------------------------------
tests :: [Test]
tests = [ testAvPairs
, testCookie
, testHeaderParse
, testQuotedString
, testUnsafeFromHex
, testUnsafeFromInt
, testUrlEncoded
, testFailParse
, testTokens
]
------------------------------------------------------------------------------
testAvPairs :: Test
testAvPairs = testCase "parsing/avpairs" $ do
let x = fullyParse txt pAvPairs
assertEqual "avpairs" (Right [ ("foo" , "bar")
, ("bar" , "baz")
, ("quux", "" )
]) x
where
txt = "foo = bar; bar = baz; quux"
------------------------------------------------------------------------------
testCookie :: Test
testCookie =
testCase "parsing/parseCookie" $ do
assertEqual "cookie parsing" (Just [cv]) cv2
let (Just [c]) = cv2
-- stupid assertions to cover the accessors
assertEqual "c1" (cookieName c) nm
assertEqual "c2" (cookieValue c) v
assertEqual "c3" (cookieExpires c) Nothing
assertEqual "c4" (cookieDomain c) Nothing
assertEqual "c5" (cookiePath c) Nothing
assertEqual "c6" (cookieSecure c) False
assertEqual "c7" (cookieHttpOnly c) False
where
cv = Cookie nm v Nothing Nothing Nothing False False
cv2 = parseCookie ct
nm = "foo"
v = "bar"
ct = S.concat [ nm , "=" , v ]
------------------------------------------------------------------------------
testHeaderParse :: Test
testHeaderParse = testCase "parsing/headers" $ do
let e = fullyParse txt pHeaders
assertEqual "parse" (Right [("foo", "bar baz quux")]) e
let f = fullyParse bad pHeaders
assertEqual "bad parse" (Right []) f
where
txt = S.concat [ "foo: bar\r\n"
, " baz\r\n"
, " quux\r\n"
]
bad = "%&^%&^*^(*&^*&^*%*&%^^#$"
------------------------------------------------------------------------------
testQuotedString :: Test
testQuotedString = testCase "parsing/quoted-string" $ do
let e = fullyParse txt pQuotedString
assertEqual "q-s" (Right "foo\"bar\"baz") e
where
txt = "\"foo\\\"bar\\\"baz\""
------------------------------------------------------------------------------
-- older random didn't have a Word8 instance.....
data WrappedWord8 = W { _unW :: Word8 }
instance Show WrappedWord8 where
show (W w) = show w
instance Random WrappedWord8 where
randomR (W a, W b) g = case randomR (fromIntegral a :: Int,
fromIntegral b :: Int) g
of (x, g') -> (W $! fromIntegral x, g')
random = randomR (W minBound, W maxBound)
instance Arbitrary WrappedWord8 where
arbitrary = choose (W minBound, W maxBound)
------------------------------------------------------------------------------
testUnsafeFromHex :: Test
testUnsafeFromHex = testCase "parsing/unsafeFromHex" $ do
expectExceptionH $ return $! ((unsafeFromHex "zz") :: Int)
let x = unsafeFromHex "a"
assertEqual "a" (10 :: Int) x
------------------------------------------------------------------------------
testUnsafeFromInt :: Test
testUnsafeFromInt = testCase "parsing/unsafeFromNat" $ do
expectExceptionH $ return $! ((unsafeFromNat "zz") :: Int)
let x = unsafeFromNat "10"
assertEqual "10" (10 :: Int) x
------------------------------------------------------------------------------
testUrlEncoded :: Test
testUrlEncoded = testCase "parsing/urlEncoded" $ do
let x = parseUrlEncoded "foo=h%20i&bar=baz+baz&baz=quux&baz=zzz&%zz"
assertEqual "map" (Map.fromList [ ("foo", ["h i"])
, ("bar", ["baz baz"])
, ("baz", ["quux", "zzz"]) ]) x
------------------------------------------------------------------------------
testFailParse :: Test
testFailParse = testCase "parsing/failParse" $ do
let (Left a) = fullyParse "foo" ((string "bar" <?> "foo") <?> "bar")
let (Left b) = fullyParse "foo" (fail "bar")
let (Left c) = fullyParse "aaaaa" (many (char 'a') >> string "b")
let f = const $ Partial f
let (Left d) = fullyParse' (const f) (const f) "aaaaa" (string "b")
let e@(Just "aaaa") = parseToCompletion (many (char 'a')) "aaaa"
let (Left g) = fullyParse "\x09" crlf
let (Done z (0::Int)) = finish $! Partial $! \s ->
s `seq` Partial (\t -> t `seq` Done t 0)
return $! length a `seq` length b `seq` length c `seq` length d `seq` e
`seq` length g `seq` z `seq` ()
------------------------------------------------------------------------------
testTokens :: Test
testTokens = testCase "parsing/tokens" $ do
assertEqual "without whitespace" (Right ["Foo","Bar"]) $
fullyParse "Foo,Bar" pTokens
assertEqual "with whitespace" (Right ["Foo","Bar"]) $
fullyParse " Foo ,Bar " pTokens