{-# LANGUAGE OverloadedStrings #-} module Main ( main ) where import Codec.Archive import Codec.Archive.Roundtrip (itPacksUnpacks, itPacksUnpacksViaFS, roundtrip, roundtripFreaky, roundtripStrict, roundtripStrict') import Codec.Archive.Test import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as BSL import Data.Either (isRight) import Data.Foldable (traverse_) import System.Directory (doesDirectoryExist, listDirectory) import System.FilePath (()) import System.IO.Temp (withSystemTempDirectory) import Control.Exception (evaluate) import Control.DeepSeq #ifdef mingw32_HOST_OS import System.Environment import Test.Hspec.Core.Runner #endif import Test.Hspec testFp :: FilePath -> Spec testFp fp = it ("sucessfully unpacks/packs (" ++ fp ++ ")") $ roundtrip fp >>= (`shouldSatisfy` isRight) testFpStrict :: FilePath -> Spec testFpStrict fp = it ("works on strict bytestring (" ++ fp ++ ")") $ roundtripStrict fp >>= (`shouldSatisfy` isRight) testFpStrict' :: FilePath -> Spec testFpStrict' fp = it ("works on strict bytestring (" ++ fp ++ ")") $ roundtripStrict' fp >>= (`shouldSatisfy` isRight) testFpFreaky :: FilePath -> Spec testFpFreaky fp = it ("works on nonstandard bytestring (" ++ fp ++ ")") $ roundtripFreaky fp >>= (`shouldSatisfy` isRight) unpack :: FilePath -> IO (Either ArchiveResult ()) unpack fp = withSystemTempDirectory "libarchive" $ \tmp -> fmap force (evaluate =<< (runArchiveM $ unpackArchive fp tmp)) readArchiveFile' :: FilePath -> IO (Either ArchiveResult [Entry FilePath BS.ByteString]) readArchiveFile' fp = evaluate =<< (runArchiveM . readArchiveFile $ fp) testUnpackLibarchive :: FilePath -> Spec testUnpackLibarchive fp = it ("unpacks " ++ fp) $ unpack fp >>= (`shouldSatisfy` isRight) testReadArchiveFile :: FilePath -> Spec testReadArchiveFile fp = it ("reads " ++ fp) $ readArchiveFile' fp >>= (`shouldSatisfy` isRight) repack :: ([Entry FilePath BS.ByteString] -> BSL.ByteString) -> String -> FilePath -> Spec repack packer str fp = it ("should repack (" ++ str ++ ")") $ do res <- fmap force (evaluate =<< (runArchiveM $ packer <$> readArchiveFile fp)) res `shouldSatisfy` bsValid bsValid :: Either a BSL.ByteString -> Bool bsValid = \x -> case x of { Left{} -> False; Right b -> not $ BSL.null b } main :: IO () main = do dir <- doesDirectoryExist "test/data" tarballs <- if dir then listDirectory "test/data" else pure [] let tarPaths = ("test/data" ) <$> tarballs hspec' $ describe "roundtrip" $ do traverse_ testFp tarPaths #ifndef LOW_MEMORY traverse_ (\fp -> repack entriesToBSLzip ("zip/" ++ fp) fp) tarPaths traverse_ (repack entriesToBSLCpio "cpio") tarPaths -- traverse_ (repack entriesToBSLXar "xar") tarPaths traverse_ (repack entriesToBSLShar "shar") tarPaths traverse_ (repack entriesToBSL7zip "7zip") tarPaths traverse_ testFpFreaky tarPaths traverse_ testFpStrict tarPaths traverse_ testFpStrict' tarPaths #endif traverse_ testUnpackLibarchive tarPaths traverse_ testReadArchiveFile tarPaths context "with symlinks" $ do let entries = [ simpleDir "x/" , simpleFile "x/a.txt" (NormalFile "referenced") , simpleFile "x/b.txt" (Symlink "a.txt" SymlinkUndefined) ] itPacksUnpacks entries itPacksUnpacksViaFS entries context "with hardlinks" $ do let entries = [ simpleDir "x/" , simpleFile "x/a.txt" (NormalFile "shared") , simpleFile "x/b.txt" (Hardlink "x/a.txt") ] itPacksUnpacks entries context "issue#4" $ itPacksUnpacksViaFS entries context "with forward referenced hardlinks" $ do let entries = [ simpleDir "x/" , simpleFile "x/b.txt" (Hardlink "x/a.txt") , simpleFile "x/a.txt" (NormalFile "shared") ] itPacksUnpacks entries xcontext "re-ordering on unpack" $ itPacksUnpacksViaFS entries xcontext "having entry without ownership" . itPacksUnpacks $ [ stripOwnership (simpleFile "a.txt" (NormalFile "text")) ] xcontext "having entry without timestamp" . itPacksUnpacks $ [ stripTime (simpleFile "a.txt" (NormalFile "text")) ] where #ifdef mingw32_HOST_OS hspec' spec = getArgs >>= readConfig defaultConfig >>= (\c -> withArgs [] . runSpec spec $ c{ configConcurrentJobs = Nothing }) >>= evaluateSummary #else hspec' = hspec #endif