File: Spec.hs

package info (click to toggle)
haskell-cookie 0.4.1.2-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 64 kB
  • sloc: haskell: 275; makefile: 2
file content (99 lines) | stat: -rw-r--r-- 3,330 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import Test.Framework (defaultMain)
import Test.Framework.Providers.QuickCheck2 (testProperty)
import Test.Framework.Providers.HUnit (testCase)
import Test.QuickCheck
import Test.HUnit ((@=?), Assertion)

import Web.Cookie
import Blaze.ByteString.Builder (Builder, toLazyByteString)
import qualified Data.ByteString as S
import qualified Data.ByteString.Char8 as S8
import qualified Data.ByteString.Lazy as L
import Data.Word (Word8)
import Control.Arrow ((***))
import Control.Applicative ((<$>), (<*>))
import Data.Time (UTCTime (UTCTime), toGregorian)
import qualified Data.Text as T

main :: IO ()
main = defaultMain
    [ testProperty "parse/render cookies" propParseRenderCookies
    , testProperty "parse/render SetCookie" propParseRenderSetCookie
    , testProperty "parse/render cookies text" propParseRenderCookiesText
    , testCase "parseCookies" caseParseCookies
    , twoDigit 24 2024
    , twoDigit 69 2069
    , twoDigit 70 1970
    ]

propParseRenderCookies :: Cookies' -> Bool
propParseRenderCookies cs' =
    parseCookies (builderToBs $ renderCookies cs) == cs
  where
    cs = map (fromUnChars *** fromUnChars) cs'

propParseRenderCookiesText :: Cookies' -> Bool
propParseRenderCookiesText cs' =
    parseCookiesText (builderToBs $ renderCookiesText cs) == cs
  where
    cs = map (T.pack . map unChar'' *** T.pack . map unChar'') cs'
    unChar'' = toEnum . fromEnum . unChar'

fromUnChars :: [Char'] -> S.ByteString
fromUnChars = S.pack . map unChar'

builderToBs :: Builder -> S.ByteString
builderToBs = S.concat . L.toChunks . toLazyByteString

type Cookies' = [([Char'], [Char'])]
newtype Char' = Char' { unChar' :: Word8 }
instance Show Char' where
    show (Char' w) = [toEnum $ fromEnum w]
    showList = (++) . show . concatMap show
instance Arbitrary Char' where
    arbitrary = fmap (Char' . toEnum) $ choose (62, 125)

propParseRenderSetCookie :: SetCookie -> Bool
propParseRenderSetCookie sc =
    parseSetCookie (builderToBs $ renderSetCookie sc) == sc

instance Arbitrary SetCookie where
    arbitrary = do
        name <- fmap fromUnChars arbitrary
        value <- fmap fromUnChars arbitrary
        path <- fmap (fmap fromUnChars) arbitrary
        expires <- fmap (parseCookieExpires . formatCookieExpires)
                    (UTCTime <$> fmap toEnum arbitrary <*> return 0)
        domain <- fmap (fmap fromUnChars) arbitrary
        httponly <- arbitrary
        secure <- arbitrary
        return def
            { setCookieName = name
            , setCookieValue = value
            , setCookiePath = path
            , setCookieExpires = expires
            , setCookieDomain = domain
            , setCookieHttpOnly = httponly
            , setCookieSecure = secure
            }

caseParseCookies :: Assertion
caseParseCookies = do
    let input = S8.pack "a=a1;b=b2; c=c3"
        expected = [("a", "a1"), ("b", "b2"), ("c", "c3")]
    map (S8.pack *** S8.pack) expected @=? parseCookies input

-- Tests for two digit years, see:
--
-- https://github.com/snoyberg/cookie/issues/5
twoDigit x y =
    testCase ("year " ++ show x) (y @=? year)
  where
    (year, _, _) = toGregorian day
    Just (UTCTime day _) = setCookieExpires sc
    sc = parseSetCookie str
    str = S8.pack $ concat
        [ "foo=bar; Expires=Mon, 29-Jul-"
        , show x
        , " 04:52:08 GMT"
        ]