{-# LANGUAGE OverloadedStrings #-} module Main where import Prelude hiding (zip) import Control.Monad import Data.ByteString.Char8 (ByteString) import qualified Data.ByteString.Char8 as B import Data.List ((\\)) import Data.Time import System.Directory import System.FilePath import System.IO import Control.Monad.State import Data.Conduit import qualified Data.Conduit.List as CL import System.IO.Temp import Test.Framework import Test.Framework.Providers.HUnit import Test.HUnit hiding (Test, path) import Codec.Archive.Zip main :: IO () main = defaultMain tests tests :: [Test] tests = [ testGroup "cases" [ testCase "conduit" assertConduit , testCase "files " assertFiles ] ] assertConduit :: Assertion assertConduit = withSystemTempDirectory "zip-conduit" $ \dir -> do let archivePath = dir archiveName archive archivePath fileName content result <- unarchive archivePath fileName assertEqual "" content result where archiveName = "test.zip" fileName = "test.txt" content = "some not really long test text" assertFiles :: Assertion assertFiles = withSystemTempDirectory "zip-conduit" $ \dir -> do -- create files filePaths <- putFiles dir filesInfo -- archive and unarchive withArchive (dir archiveName) $ do addFiles filePaths names <- fileNames extractFiles names dir -- read unarchived files result <- getFiles dir -- compare assertEqual "" [] (filesInfo \\ result) where archiveName = "test.zip" filesInfo = [ ("test1.txt", "some test text") , ("test2.txt", "some another test text") , ("test3.txt", "one more") ] putFiles :: FilePath -> [(FilePath, ByteString)] -> IO [FilePath] putFiles dir fileInfo = forM fileInfo $ \(name, content) -> do let path = dir name withFile path WriteMode $ \h -> do B.hPut h content return path getFiles :: FilePath -> IO [(FilePath, ByteString)] getFiles dir = do let path = dir dropDrive dir dirContents <- getDirectoryContents path let resultFiles = map (path ) $ filter (`notElem` [".", ".."]) dirContents forM resultFiles $ \file -> do content <- withFile file ReadMode B.hGetContents return (takeFileName file, content) -- | Creates new archive at 'archivePath' and puts there file with -- 'content'. archive :: FilePath -> FilePath -> ByteString -> IO () archive archivePath fileName content = do time <- liftIO getCurrentTime withArchive archivePath $ do sink <- getSink fileName time runResourceT $ CL.sourceList [content] $$ sink -- | Gets content from 'fileName' in archive at 'arcihvePath'. unarchive :: FilePath -> FilePath -> IO ByteString unarchive archivePath fileName = do withArchive archivePath $ do source <- getSource fileName runResourceT $ source $$ CL.fold B.append ""