{-# LANGUAGE BangPatterns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} module Snap.Util.FileServe.Tests ( tests ) where import Control.Monad import Data.ByteString (ByteString) import qualified Data.ByteString.Char8 as B import qualified Data.ByteString.Lazy.Char8 as L import Data.IORef import qualified Data.Map as Map import Data.Maybe import Prelude hiding (take) import Test.Framework import Test.Framework.Providers.HUnit import Test.HUnit hiding (Test, path) import Snap.Internal.Http.Types import Snap.Internal.Types import Snap.Util.FileServe import Snap.Iteratee tests :: [Test] tests = [ testFs ] expect404 :: IO Response -> IO () expect404 m = do r <- m assertBool "expected 404" (rspStatus r == 404) getBody :: Response -> IO L.ByteString getBody r = liftM fromWrap ((rspBodyToEnum $ rspBody r) stream2stream >>= run) go :: Snap a -> ByteString -> IO Response go m s = do rq <- mkRequest s liftM snd (run $ runSnap m (const $ return ()) rq) goIfModifiedSince :: Snap a -> ByteString -> ByteString -> IO Response goIfModifiedSince m s lm = do rq <- mkRequest s let r = setHeader "if-modified-since" lm rq liftM snd (run $ runSnap m (const $ return ()) r) mkRequest :: ByteString -> IO Request mkRequest uri = do enum <- newIORef $ SomeEnumerator return return $ Request "foo" 80 "foo" 999 "foo" 1000 "foo" False Map.empty enum Nothing GET (1,1) [] "" uri "/" (B.concat ["/",uri]) "" Map.empty fs :: Snap () fs = fileServe "data/fileServe" testFs :: Test testFs = testCase "fileServe" $ do r1 <- go fs "foo.bin" b1 <- getBody r1 assertEqual "foo.bin" "FOO\n" b1 assertEqual "foo.bin content-type" (Just "application/octet-stream") (getHeader "content-type" r1) assertEqual "foo.bin size" (Just 4) (rspContentLength r1) assertBool "last-modified header" (isJust $ getHeader "last-modified" r1) let !lm = fromJust $ getHeader "last-modified" r1 -- check last modified stuff r2 <- goIfModifiedSince fs "foo.bin" lm assertEqual "foo.bin 304" 304 $ rspStatus r2 r3 <- goIfModifiedSince fs "foo.bin" "Wed, 15 Nov 1995 04:58:08 GMT" assertEqual "foo.bin 200" 200 $ rspStatus r3 b3 <- getBody r3 assertEqual "foo.bin 2" "FOO\n" b3 r4 <- go fs "foo.txt" b4 <- getBody r4 assertEqual "foo.txt" "FOO\n" b4 assertEqual "foo.txt content-type" (Just "text/plain") (getHeader "content-type" r4) r5 <- go fs "foo.html" b5 <- getBody r5 assertEqual "foo.html" "FOO\n" b5 assertEqual "foo.html content-type" (Just "text/html") (getHeader "content-type" r5) r6 <- go fs "foo.bin.bin.bin" b6 <- getBody r6 assertEqual "foo.bin.bin.bin" "FOO\n" b6 assertEqual "foo.bin.bin.bin content-type" (Just "application/octet-stream") (getHeader "content-type" r6) expect404 $ go fs "jfldksjflksd" expect404 $ go fs "dummy/../foo.txt" expect404 $ go fs "/etc/password" coverMimeMap coverMimeMap :: (Monad m) => m () coverMimeMap = mapM_ f $ Map.toList defaultMimeTypes where f (!k,!v) = return $ case k `seq` v `seq` () of () -> ()