Skip to content

Commit e3da415

Browse files
committed
Add tests for _ZlibDecompressor
1 parent 9d60339 commit e3da415

File tree

1 file changed

+167
-0
lines changed

1 file changed

+167
-0
lines changed

Lib/test/test_zlib.py

+167
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,173 @@ def choose_lines(source, number, seed=None, generator=random):
944944
"""
945945

946946

947+
class ZlibDecompressorTest():
948+
# Test adopted from test_bz2.py
949+
TEXT = HAMLET_SCENE
950+
DATA = zlib.compress(HAMLET_SCENE)
951+
BAD_DATA = b"Not a valid deflate block"
952+
def test_Constructor(self):
953+
self.assertRaises(TypeError, zlib._ZlibDecompressor, 42)
954+
955+
def testDecompress(self):
956+
zlibd = zlib._ZlibDecompressor()
957+
self.assertRaises(TypeError, zlibd.decompress)
958+
text = zlibd.decompress(self.DATA)
959+
self.assertEqual(text, self.TEXT)
960+
961+
def testDecompressChunks10(self):
962+
zlibd = zlib._ZlibDecompressor()
963+
text = b''
964+
n = 0
965+
while True:
966+
str = self.DATA[n*10:(n+1)*10]
967+
if not str:
968+
break
969+
text += zlibd.decompress(str)
970+
n += 1
971+
self.assertEqual(text, self.TEXT)
972+
973+
def testDecompressUnusedData(self):
974+
zlibd = zlib._ZlibDecompressor()
975+
unused_data = b"this is unused data"
976+
text = zlibd.decompress(self.DATA+unused_data)
977+
self.assertEqual(text, self.TEXT)
978+
self.assertEqual(zlibd.unused_data, unused_data)
979+
980+
def testEOFError(self):
981+
zlibd = zlib._ZlibDecompressor()
982+
text = zlibd.decompress(self.DATA)
983+
self.assertRaises(EOFError, zlibd.decompress, b"anything")
984+
self.assertRaises(EOFError, zlibd.decompress, b"")
985+
986+
@support.skip_if_pgo_task
987+
@bigmemtest(size=_4G + 100, memuse=3.3)
988+
def testDecompress4G(self, size):
989+
# "Test zlib._ZlibDecompressor.decompress() with >4GiB input"
990+
blocksize = 10 * 1024 * 1024
991+
block = random.randbytes(blocksize)
992+
try:
993+
data = block * (size // blocksize + 1)
994+
compressed = zlib.compress(data)
995+
zlibd = zlib._ZlibDecompressor()
996+
decompressed = zlibd.decompress(compressed)
997+
self.assertTrue(decompressed == data)
998+
finally:
999+
data = None
1000+
compressed = None
1001+
decompressed = None
1002+
1003+
def testPickle(self):
1004+
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
1005+
with self.assertRaises(TypeError):
1006+
pickle.dumps(zlib._ZlibDecompressor(), proto)
1007+
1008+
def testDecompressorChunksMaxsize(self):
1009+
zlibd = zlib._ZlibDecompressor()
1010+
max_length = 100
1011+
out = []
1012+
1013+
# Feed some input
1014+
len_ = len(self.BIG_DATA) - 64
1015+
out.append(zlibd.decompress(self.BIG_DATA[:len_],
1016+
max_length=max_length))
1017+
self.assertFalse(zlibd.needs_input)
1018+
self.assertEqual(len(out[-1]), max_length)
1019+
1020+
# Retrieve more data without providing more input
1021+
out.append(zlibd.decompress(b'', max_length=max_length))
1022+
self.assertFalse(zlibd.needs_input)
1023+
self.assertEqual(len(out[-1]), max_length)
1024+
1025+
# Retrieve more data while providing more input
1026+
out.append(zlibd.decompress(self.BIG_DATA[len_:],
1027+
max_length=max_length))
1028+
self.assertLessEqual(len(out[-1]), max_length)
1029+
1030+
# Retrieve remaining uncompressed data
1031+
while not zlibd.eof:
1032+
out.append(zlibd.decompress(b'', max_length=max_length))
1033+
self.assertLessEqual(len(out[-1]), max_length)
1034+
1035+
out = b"".join(out)
1036+
self.assertEqual(out, self.BIG_TEXT)
1037+
self.assertEqual(zlibd.unused_data, b"")
1038+
1039+
def test_decompressor_inputbuf_1(self):
1040+
# Test reusing input buffer after moving existing
1041+
# contents to beginning
1042+
zlibd = zlib._ZlibDecompressor()
1043+
out = []
1044+
1045+
# Create input buffer and fill it
1046+
self.assertEqual(zlibd.decompress(self.DATA[:100],
1047+
max_length=0), b'')
1048+
1049+
# Retrieve some results, freeing capacity at beginning
1050+
# of input buffer
1051+
out.append(zlibd.decompress(b'', 2))
1052+
1053+
# Add more data that fits into input buffer after
1054+
# moving existing data to beginning
1055+
out.append(zlibd.decompress(self.DATA[100:105], 15))
1056+
1057+
# Decompress rest of data
1058+
out.append(zlibd.decompress(self.DATA[105:]))
1059+
self.assertEqual(b''.join(out), self.TEXT)
1060+
1061+
def test_decompressor_inputbuf_2(self):
1062+
# Test reusing input buffer by appending data at the
1063+
# end right away
1064+
zlibd = zlib._ZlibDecompressor()
1065+
out = []
1066+
1067+
# Create input buffer and empty it
1068+
self.assertEqual(zlibd.decompress(self.DATA[:200],
1069+
max_length=0), b'')
1070+
out.append(zlibd.decompress(b''))
1071+
1072+
# Fill buffer with new data
1073+
out.append(zlibd.decompress(self.DATA[200:280], 2))
1074+
1075+
# Append some more data, not enough to require resize
1076+
out.append(zlibd.decompress(self.DATA[280:300], 2))
1077+
1078+
# Decompress rest of data
1079+
out.append(zlibd.decompress(self.DATA[300:]))
1080+
self.assertEqual(b''.join(out), self.TEXT)
1081+
1082+
def test_decompressor_inputbuf_3(self):
1083+
# Test reusing input buffer after extending it
1084+
1085+
zlibd = zlib._ZlibDecompressor()
1086+
out = []
1087+
1088+
# Create almost full input buffer
1089+
out.append(zlibd.decompress(self.DATA[:200], 5))
1090+
1091+
# Add even more data to it, requiring resize
1092+
out.append(zlibd.decompress(self.DATA[200:300], 5))
1093+
1094+
# Decompress rest of data
1095+
out.append(zlibd.decompress(self.DATA[300:]))
1096+
self.assertEqual(b''.join(out), self.TEXT)
1097+
1098+
def test_failure(self):
1099+
zlibd = zlib._ZlibDecompressor()
1100+
self.assertRaises(Exception, zlibd.decompress, self.BAD_DATA * 30)
1101+
# Previously, a second call could crash due to internal inconsistency
1102+
self.assertRaises(Exception, zlibd.decompress, self.BAD_DATA * 30)
1103+
1104+
@support.refcount_test
1105+
def test_refleaks_in___init__(self):
1106+
gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount')
1107+
zlibd = zlib._ZlibDecompressor()
1108+
refs_before = gettotalrefcount()
1109+
for i in range(100):
1110+
zlibd.__init__()
1111+
self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10)
1112+
1113+
9471114
class CustomInt:
9481115
def __index__(self):
9491116
return 100

0 commit comments

Comments
 (0)