From fd64fce1887a4632ad7f5b483234902b26f8e894 Mon Sep 17 00:00:00 2001
From: Oleg Grenrus <oleg.grenrus@iki.fi>
Date: Wed, 24 Jun 2015 14:43:56 +0300
Subject: [PATCH] Correct maybeDecompress

---
 .../Distribution/Client/GZipUtils.hs          |  4 +--
 .../Distribution/Client/GZipUtils.hs          | 28 +++++++++++++++++--
 2 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/cabal-install/Distribution/Client/GZipUtils.hs b/cabal-install/Distribution/Client/GZipUtils.hs
index 0abc463c21..f5d688faf5 100644
--- a/cabal-install/Distribution/Client/GZipUtils.hs
+++ b/cabal-install/Distribution/Client/GZipUtils.hs
@@ -50,7 +50,7 @@ maybeDecompress bytes = runST (go bytes decompressor)
     -- at the beginning of the gzip header.  (not an option for zlib, though.)
     go :: Monad m => ByteString -> DecompressStream m -> m ByteString
     go cs (DecompressOutputAvailable bs k) = liftM (Chunk bs) $ go' cs =<< k
-    go _  (DecompressStreamEnd       bs  ) = return $ Chunk bs Empty
+    go _  (DecompressStreamEnd       _bs ) = return Empty
     go _  (DecompressStreamError _err    ) = return bytes
     go cs (DecompressInputRequired      k) = go cs' =<< k c
       where
@@ -61,7 +61,7 @@ maybeDecompress bytes = runST (go bytes decompressor)
     -- TODO: We could (and should) avoid these pure exceptions.
     go' :: Monad m => ByteString -> DecompressStream m -> m ByteString
     go' cs (DecompressOutputAvailable bs k) = liftM (Chunk bs) $ go' cs =<< k
-    go' _  (DecompressStreamEnd       bs  ) = return $ Chunk bs Empty
+    go' _  (DecompressStreamEnd       _bs ) = return Empty
     go' _  (DecompressStreamError err     ) = throw err
     go' cs (DecompressInputRequired      k) = go' cs' =<< k c
       where
diff --git a/cabal-install/tests/UnitTests/Distribution/Client/GZipUtils.hs b/cabal-install/tests/UnitTests/Distribution/Client/GZipUtils.hs
index 5ac14fe362..19808233db 100644
--- a/cabal-install/tests/UnitTests/Distribution/Client/GZipUtils.hs
+++ b/cabal-install/tests/UnitTests/Distribution/Client/GZipUtils.hs
@@ -7,15 +7,22 @@ import Codec.Compression.Zlib          as Zlib
 import Control.Exception.Base                  (evaluate)
 import Control.Exception                       (try, SomeException)
 import Control.Monad                           (void)
-import Data.ByteString.Lazy.Char8     as BS    (pack, init, length)
+import Data.ByteString                as BS    (null)
+import Data.ByteString.Lazy           as BSL   (pack, toChunks)
+import Data.ByteString.Lazy.Char8     as BSLL  (pack, init, length)
 import Data.Monoid                             ((<>))
 import Distribution.Client.GZipUtils           (maybeDecompress)
+import Data.Word                               (Word8)
 
 import Test.Tasty
 import Test.Tasty.HUnit
+import Test.Tasty.QuickCheck
 
 tests :: [TestTree]
 tests = [ testCase "maybeDecompress" maybeDecompressUnitTest
+        , testProperty "decompress plain" prop_maybeDecompress_plain
+        , testProperty "decompress zlib"  prop_maybeDecompress_zlib
+        , testProperty "decompress gzip"  prop_maybeDecompress_gzip
         ]
 
 maybeDecompressUnitTest :: Assertion
@@ -25,14 +32,29 @@ maybeDecompressUnitTest =
      >> assertBool "decompress gzip (with show)" (show (maybeDecompress compressedGZip) == show original)
      >> assertBool "decompress zlib"             (maybeDecompress compressedZlib        == original)
      >> assertBool "decompress gzip"             (maybeDecompress compressedGZip        == original)
+     >> assertBool "have no empty chunks"        (Prelude.all (not . BS.null) . BSL.toChunks . maybeDecompress $ compressedZlib)
      >> (runBrokenStream >>= assertBool "decompress broken stream" . isLeft)
   where
-    original = BS.pack "original uncompressed input"
+    original = BSLL.pack "original uncompressed input"
     compressedZlib = Zlib.compress original
     compressedGZip = GZip.compress original
 
     runBrokenStream :: IO (Either SomeException ())
-    runBrokenStream = try . void . evaluate . BS.length $ maybeDecompress (BS.init compressedZlib <> BS.pack "*")
+    runBrokenStream = try . void . evaluate . BSLL.length $ maybeDecompress (BSLL.init compressedZlib <> BSLL.pack "*")
+
+prop_maybeDecompress_plain :: [Word8] -> Property
+prop_maybeDecompress_plain ws = property $ maybeDecompress original == original
+  where original = BSL.pack ws
+
+prop_maybeDecompress_zlib :: [Word8] -> Property
+prop_maybeDecompress_zlib ws = property $ maybeDecompress compressedZlib == original
+  where original = BSL.pack ws
+        compressedZlib = Zlib.compress original
+
+prop_maybeDecompress_gzip :: [Word8] -> Property
+prop_maybeDecompress_gzip ws = property $ maybeDecompress compressedGZip == original
+  where original = BSL.pack ws
+        compressedGZip = GZip.compress original
 
 -- (Only available from "Data.Either" since 7.8.)
 isLeft :: Either a b -> Bool
-- 
GitLab