@@ -28,14 +28,16 @@ import Prelude hiding (catch)
28
28
#endif
29
29
30
30
31
-
32
31
main :: IO ()
33
32
main = defaultMain $
34
33
testGroup " zlib tests" [
35
34
testGroup " property tests" [
36
35
testProperty " decompress . compress = id (standard)" prop_decompress_after_compress,
37
36
testProperty " decompress . compress = id (Zlib -> GZipOrZLib)" prop_gziporzlib1,
38
37
testProperty " decompress . compress = id (GZip -> GZipOrZlib)" prop_gziporzlib2,
38
+ testProperty " concatenated gzip members" prop_gzip_concat,
39
+ testProperty " multiple gzip members, boundaries (all 2-chunks)" prop_multiple_members_boundary2,
40
+ testProperty " multiple gzip members, boundaries (all 3-chunks)" prop_multiple_members_boundary3,
39
41
testProperty " prefixes of valid stream detected as truncated" prop_truncated
40
42
],
41
43
testGroup " unit tests" [
@@ -46,6 +48,7 @@ main = defaultMain $
46
48
testCase " dectect inflate with wrong dict" test_wrong_dictionary,
47
49
testCase " dectect inflate with right dict" test_right_dictionary,
48
50
testCase " handle trailing data" test_trailing_data,
51
+ testCase " multiple gzip members" test_multiple_members,
49
52
testCase " check small input chunks" test_small_chunks,
50
53
testCase " check exception raised" test_exception
51
54
]
@@ -83,6 +86,42 @@ prop_gziporzlib2 cp dp =
83
86
decompressBufferSize dp > 0 && compressBufferSize cp > 0 ==>
84
87
liftM2 (==) (decompress gzipOrZlibFormat dp . compress gzipFormat cp) id
85
88
89
+ prop_gzip_concat :: CompressParams
90
+ -> DecompressParams
91
+ -> BL. ByteString
92
+ -> Property
93
+ prop_gzip_concat cp dp input =
94
+ decompressWindowBits dp >= compressWindowBits cp &&
95
+ decompressBufferSize dp > 0 && compressBufferSize cp > 0 ==>
96
+ let catComp = BL. concat (replicate 5 (compress gzipFormat cp input))
97
+ compCat = compress gzipFormat cp (BL. concat (replicate 5 input))
98
+
99
+ in decompress gzipFormat dp { decompressAllMembers = True } catComp
100
+ == decompress gzipFormat dp { decompressAllMembers = True } compCat
101
+
102
+ prop_multiple_members_boundary2 :: Property
103
+ prop_multiple_members_boundary2 =
104
+ forAll shortStrings $ \ bs ->
105
+ all (\ c -> decomp c == BL. append bs bs)
106
+ (twoChunkSplits (comp bs `BL.append` comp bs))
107
+ where
108
+ comp = compress gzipFormat defaultCompressParams
109
+ decomp = decompress gzipFormat defaultDecompressParams
110
+
111
+ shortStrings = fmap BL. pack $ listOf arbitrary
112
+
113
+ prop_multiple_members_boundary3 :: Property
114
+ prop_multiple_members_boundary3 =
115
+ forAll shortStrings $ \ bs ->
116
+ all (\ c -> decomp c == BL. append bs bs)
117
+ (threeChunkSplits (comp bs `BL.append` comp bs))
118
+ where
119
+ comp = compress gzipFormat defaultCompressParams
120
+ decomp = decompress gzipFormat defaultDecompressParams
121
+
122
+ shortStrings = sized $ \ sz -> resize (sz `div` 10 ) $
123
+ fmap BL. pack $ listOf arbitrary
124
+
86
125
prop_truncated :: Format -> Property
87
126
prop_truncated format =
88
127
forAll shortStrings $ \ bs ->
@@ -170,12 +209,27 @@ test_right_dictionary = do
170
209
test_trailing_data :: Assertion
171
210
test_trailing_data =
172
211
withSampleData " two-files.gz" $ \ hnd -> do
173
- let decomp = decompressIO gzipFormat defaultDecompressParams
212
+ let decomp = decompressIO gzipFormat defaultDecompressParams {
213
+ decompressAllMembers = False
214
+ }
174
215
chunks <- assertDecompressOkChunks hnd decomp
175
216
case chunks of
176
217
[chunk] -> chunk @?= BS.Char8. pack " Test 1"
177
218
_ -> assertFailure " expected single chunk"
178
219
220
+ test_multiple_members :: Assertion
221
+ test_multiple_members =
222
+ withSampleData " two-files.gz" $ \ hnd -> do
223
+ let decomp = decompressIO gzipFormat defaultDecompressParams {
224
+ decompressAllMembers = True
225
+ }
226
+ chunks <- assertDecompressOkChunks hnd decomp
227
+ case chunks of
228
+ [chunk1,
229
+ chunk2] -> do chunk1 @?= BS.Char8. pack " Test 1"
230
+ chunk2 @?= BS.Char8. pack " Test 2"
231
+ _ -> assertFailure " expected two chunks"
232
+
179
233
test_small_chunks :: Assertion
180
234
test_small_chunks = do
181
235
uncompressedFile <- readSampleData " not-gzip"
@@ -190,9 +244,6 @@ test_small_chunks = do
190
244
compressedFile <- readSampleData " hello.gz"
191
245
(GZip. decompress . smallChunks) compressedFile @?= GZip. decompress compressedFile
192
246
193
- where
194
- smallChunks :: BL. ByteString -> BL. ByteString
195
- smallChunks = BL. fromChunks . map (\ c -> BS. pack [c]) . BL. unpack
196
247
197
248
test_exception :: Assertion
198
249
test_exception =
@@ -212,6 +263,25 @@ toStrict = BL.toStrict
212
263
toStrict = BS. concat . BL. toChunks
213
264
#endif
214
265
266
+ -----------------------
267
+ -- Chunk boundary utils
268
+
269
+ smallChunks :: BL. ByteString -> BL. ByteString
270
+ smallChunks = BL. fromChunks . map (\ c -> BS. pack [c]) . BL. unpack
271
+
272
+ twoChunkSplits :: BL. ByteString -> [BL. ByteString ]
273
+ twoChunkSplits bs = zipWith (\ a b -> BL. fromChunks [a,b]) (BS. inits sbs) (BS. tails sbs)
274
+ where
275
+ sbs = toStrict bs
276
+
277
+ threeChunkSplits :: BL. ByteString -> [BL. ByteString ]
278
+ threeChunkSplits bs =
279
+ [ BL. fromChunks [a,b,c]
280
+ | (a,x) <- zip (BS. inits sbs) (BS. tails sbs)
281
+ , (b,c) <- zip (BS. inits x) (BS. tails x) ]
282
+ where
283
+ sbs = toStrict bs
284
+
215
285
--------------
216
286
-- HUnit Utils
217
287
0 commit comments