Skip to content

Commit cf6f4a5

Browse files
committed
Add igzipdecompressor tests
1 parent 9c3d410 commit cf6f4a5

File tree

2 files changed

+166
-4
lines changed

2 files changed

+166
-4
lines changed

src/isal/igzip_lib.pyi

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,15 @@ def compress(data, level: int = ..., flag: int = ..., hist_bits: int = ...
5050
) -> bytes: ...
5151
def decompress(data, flag: int = ..., hist_bits: int = ..., bufsize: int = ...
5252
) -> bytes: ...
53+
54+
class IgzipDecompressor:
55+
unused_data: bytes
56+
eof: bool
57+
needs_input: bool
58+
59+
def __new__(cls,
60+
flag: int = DECOMP_DEFLATE,
61+
hist_bits: int = MAX_HIST_BITS,
62+
zdict = None) -> IgzipDecompressor: ...
63+
64+
def decompress(self, data, max_length: int = -1) -> bytes: ...

tests/test_igzip_lib.py

Lines changed: 154 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,12 @@
1919
# SOFTWARE.
2020

2121
import itertools
22+
import os
23+
import pickle
2224
from typing import NamedTuple
2325

2426
from isal import igzip_lib
27+
from isal.igzip_lib import IgzipDecompressor
2528

2629
import pytest
2730

@@ -57,9 +60,156 @@ def test_compress_decompress(level, flag: Flag, hist_bits):
5760

5861

5962
class TestIgzipDecompressor():
60-
compressed = igzip_lib.compress(DATA)
63+
# Tests adopted from CPython's test_bz2.py
64+
TEXT = DATA
65+
DATA = igzip_lib.compress(DATA)
66+
BAD_DATA = b"Not a valid deflate block"
6167

6268
def test_decompress(self):
63-
decomp = igzip_lib.IgzipDecompressor()
64-
decompressed = decomp.decompress(self.compressed)
65-
assert decompressed == DATA
69+
decomp = IgzipDecompressor()
70+
decompressed = decomp.decompress(self.DATA)
71+
assert decompressed == self.TEXT
72+
73+
def testDecompressChunks10(self):
74+
igzd = IgzipDecompressor()
75+
text = b''
76+
n = 0
77+
while True:
78+
str = self.DATA[n*10:(n+1)*10]
79+
if not str:
80+
break
81+
text += igzd.decompress(str)
82+
n += 1
83+
assert text == self.TEXT
84+
85+
def testDecompressUnusedData(self):
86+
igzd = IgzipDecompressor()
87+
unused_data = b"this is unused data"
88+
text = igzd.decompress(self.DATA+unused_data)
89+
assert text == self.TEXT
90+
assert igzd.unused_data == unused_data
91+
92+
def testEOFError(self):
93+
igzd = IgzipDecompressor()
94+
igzd.decompress(self.DATA)
95+
with pytest.raises(EOFError):
96+
igzd.decompress(b"anything")
97+
with pytest.raises(EOFError):
98+
igzd.decompress(b"")
99+
100+
def testDecompress4G(self):
101+
# "Test igzdecompressor.decompress() with >4GiB input"
102+
size = 4 * 1024 ** 3 + 100 # 4 GiB + 100
103+
blocksize = 10 * 1024 * 1024
104+
block = os.urandom(blocksize)
105+
try:
106+
data = block * (size // blocksize + 1)
107+
compressed = igzip_lib.compress(data)
108+
igzd = IgzipDecompressor()
109+
decompressed = igzd.decompress(compressed)
110+
assert decompressed == data
111+
finally:
112+
data = None
113+
compressed = None
114+
decompressed = None
115+
116+
def testPickle(self):
117+
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
118+
with pytest.raises(TypeError):
119+
pickle.dumps(IgzipDecompressor(), proto)
120+
121+
def testDecompressorChunksMaxsize(self):
122+
igzd = IgzipDecompressor()
123+
max_length = 100
124+
out = []
125+
126+
# Feed some input
127+
len_ = len(self.DATA) - 64
128+
out.append(igzd.decompress(self.DATA[:len_],
129+
max_length=max_length))
130+
assert not igzd.needs_input
131+
assert len(out[-1]) == max_length
132+
133+
# Retrieve more data without providing more input
134+
out.append(igzd.decompress(b'', max_length=max_length))
135+
assert not igzd.needs_input
136+
assert len(out[-1]) == max_length
137+
138+
# Retrieve more data while providing more input
139+
out.append(igzd.decompress(self.BIG_DATA[len_:],
140+
max_length=max_length))
141+
assert len(out[-1]) == max_length
142+
143+
# Retrieve remaining uncompressed data
144+
while not igzd.eof:
145+
out.append(igzd.decompress(b'', max_length=max_length))
146+
assert len(out[-1]) <= max_length
147+
148+
out = b"".join(out)
149+
assert out == self.TEXT
150+
assert igzd.unused_data == b""
151+
152+
def test_decompressor_inputbuf_1(self):
153+
# Test reusing input buffer after moving existing
154+
# contents to beginning
155+
igzd = IgzipDecompressor()
156+
out = []
157+
158+
# Create input buffer and fill it
159+
assert igzd.decompress(self.DATA[:100], max_length=0) == b''
160+
161+
# Retrieve some results, freeing capacity at beginning
162+
# of input buffer
163+
out.append(igzd.decompress(b'', 2))
164+
165+
# Add more data that fits into input buffer after
166+
# moving existing data to beginning
167+
out.append(igzd.decompress(self.DATA[100:105], 15))
168+
169+
# Decompress rest of data
170+
out.append(igzd.decompress(self.DATA[105:]))
171+
assert b''.join(out) == self.TEXT
172+
173+
def test_decompressor_inputbuf_2(self):
174+
# Test reusing input buffer by appending data at the
175+
# end right away
176+
igzd = IgzipDecompressor()
177+
out = []
178+
179+
# Create input buffer and empty it
180+
assert igzd.decompress(self.DATA[:200], max_length=0) == b''
181+
out.append(igzd.decompress(b''))
182+
183+
# Fill buffer with new data
184+
out.append(igzd.decompress(self.DATA[200:280], 2))
185+
186+
# Append some more data, not enough to require resize
187+
out.append(igzd.decompress(self.DATA[280:300], 2))
188+
189+
# Decompress rest of data
190+
out.append(igzd.decompress(self.DATA[300:]))
191+
assert b''.join(out) == self.TEXT
192+
193+
def test_decompressor_inputbuf_3(self):
194+
# Test reusing input buffer after extending it
195+
196+
igzd = IgzipDecompressor()
197+
out = []
198+
199+
# Create almost full input buffer
200+
out.append(igzd.decompress(self.DATA[:200], 5))
201+
202+
# Add even more data to it, requiring resize
203+
out.append(igzd.decompress(self.DATA[200:300], 5))
204+
205+
# Decompress rest of data
206+
out.append(igzd.decompress(self.DATA[300:]))
207+
assert b''.join(out) == self.TEXT
208+
209+
def test_failure(self):
210+
igzd = IgzipDecompressor()
211+
with pytest.raises(Exception):
212+
igzd.decompress(self.BAD_DATA * 30)
213+
# Make sure there are no internal consistencies
214+
with pytest.raises(Exception):
215+
igzd.decompress(self.BAD_DATA * 30)

0 commit comments

Comments
 (0)