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
|
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE OverloadedStrings #-}
module Data.Conduit.ZlibSpec (spec) where
import Test.Hspec
import Test.Hspec.QuickCheck (prop)
import Data.Conduit ((.|), runConduit)
import qualified Data.Conduit as C
import qualified Data.Conduit.List as CL
import qualified Data.Conduit.Zlib as CZ
import qualified Data.ByteString as S
import qualified Data.ByteString.Lazy as L
import Data.ByteString.Char8 ()
import Data.ByteString.Lazy.Char8 ()
import Control.Monad (replicateM_)
spec :: Spec
spec = describe "Data.Conduit.Zlib" $ do
prop "idempotent" $ \bss' -> do
let bss = map S.pack bss'
lbs = L.fromChunks bss
src = mconcat $ map (CL.sourceList . return) bss
outBss <- runConduit $ src .| CZ.gzip .| CZ.ungzip .| CL.consume
L.fromChunks outBss `shouldBe` lbs
prop "flush" $ \bss' -> do
let bss = map S.pack $ filter (not . null) bss'
bssC = concatMap (\bs -> [C.Chunk bs, C.Flush]) bss
src = mconcat $ map (CL.sourceList . return) bssC
outBssC <- runConduit
$ src
.| CZ.compressFlush 5 (CZ.WindowBits 31)
.| CZ.decompressFlush (CZ.WindowBits 31)
.| CL.consume
outBssC `shouldBe` bssC
it "compressFlush large data" $ do
let content = L.pack $ map (fromIntegral . fromEnum) $ concat $ ["BEGIN"] ++ map show [1..100000 :: Int] ++ ["END"]
src = CL.sourceList $ map C.Chunk $ L.toChunks content
bssC <- runConduit $ src .| CZ.compressFlush 5 (CZ.WindowBits 31) .| CL.consume
let unChunk (C.Chunk x) = [x]
unChunk C.Flush = []
bss <- runConduit $ CL.sourceList bssC .| CL.concatMap unChunk .| CZ.ungzip .| CL.consume
L.fromChunks bss `shouldBe` content
it "uncompressed after compressed" $ do
let c = "This data is stored compressed."
u = "This data isn't."
let src1 = do
C.yield c .| CZ.gzip
C.yield u
encoded <- runConduit $ src1 .| CL.consume
let src2 = mapM_ C.yield encoded
(c', u') <- runConduit $ src2 .| do
c' <- CZ.ungzip .| CL.consume
u' <- CL.consume
return (S.concat c', S.concat u')
c' `shouldBe` c
u' `shouldBe` u
it "multiple compressed values" $ do
let s1 = "hello"
s2 = "world"
src = do
C.yield s1 .| CZ.gzip
C.yield s2 .| CZ.gzip
actual <- runConduit $ src .| CZ.multiple CZ.ungzip .| CL.consume
S.concat actual `shouldBe` S.concat [s1, s2]
it "single compressed, multiple uncompressed chunks" $ do
let s1 = "hello"
s2 = "there"
s3 = "world"
s1Z <- fmap S.concat $ runConduit $ C.yield s1 .| CZ.gzip .| CL.consume
let src = do
C.yield $ S.append s1Z s2
C.yield s3
actual <- runConduit $ src .| do
x <- fmap S.concat $ CZ.ungzip .| CL.consume
y <- CL.consume
return (x, y)
actual `shouldBe` (s1, [s2, s3])
it "multiple, over 32k" $ do
let str = "One line"
cnt = 30000
src = replicateM_ cnt $ C.yield str .| CZ.gzip
actual <- fmap S.concat $ runConduit $ src .| CZ.multiple CZ.ungzip .| CL.consume
let expected = S.concat (replicate cnt str)
S.length actual `shouldBe` S.length expected
actual `shouldBe` expected
|