Mercurial > public > mercurial-scm > hg
comparison contrib/python-zstandard/tests/test_decompressor.py @ 40121:73fef626dae3
zstandard: vendor python-zstandard 0.10.1
This was just released.
The upstream source distribution from PyPI was extracted. Unwanted
files were removed.
The clang-format ignore list was updated to reflect the new source
of files.
setup.py was updated to pass a new argument to python-zstandard's
function for returning an Extension instance. Upstream had to change
to use relative paths because Python 3.7's packaging doesn't
seem to like absolute paths when defining sources, includes, etc.
The default relative path calculation is relative to setup_zstd.py
which is different from the directory of Mercurial's setup.py.
The project contains a vendored copy of zstandard 1.3.6. The old
version was 1.3.4.
The API should be backwards compatible and nothing in core should
need adjusted. However, there is a new "chunker" API that we
may find useful in places where we want to emit compressed chunks
of a fixed size.
There are a pair of bug fixes in 0.10.0 with regards to
compressobj() and decompressobj() when block flushing is used. I
actually found these bugs when introducing these APIs in Mercurial!
But existing Mercurial code is not affected because we don't
perform block flushing.
# no-check-commit because 3rd party code has different style guidelines
Differential Revision: https://phab.mercurial-scm.org/D4911
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Mon, 08 Oct 2018 16:27:40 -0700 |
parents | b1fb341d8a61 |
children | 675775c33ab6 |
comparison
equal
deleted
inserted
replaced
40120:89742f1fa6cb | 40121:73fef626dae3 |
---|---|
291 @make_cffi | 291 @make_cffi |
292 class TestDecompressor_stream_reader(unittest.TestCase): | 292 class TestDecompressor_stream_reader(unittest.TestCase): |
293 def test_context_manager(self): | 293 def test_context_manager(self): |
294 dctx = zstd.ZstdDecompressor() | 294 dctx = zstd.ZstdDecompressor() |
295 | 295 |
296 reader = dctx.stream_reader(b'foo') | |
297 with self.assertRaisesRegexp(zstd.ZstdError, 'read\(\) must be called from an active'): | |
298 reader.read(1) | |
299 | |
300 with dctx.stream_reader(b'foo') as reader: | 296 with dctx.stream_reader(b'foo') as reader: |
301 with self.assertRaisesRegexp(ValueError, 'cannot __enter__ multiple times'): | 297 with self.assertRaisesRegexp(ValueError, 'cannot __enter__ multiple times'): |
302 with reader as reader2: | 298 with reader as reader2: |
303 pass | 299 pass |
304 | 300 |
329 | 325 |
330 def test_constant_methods(self): | 326 def test_constant_methods(self): |
331 dctx = zstd.ZstdDecompressor() | 327 dctx = zstd.ZstdDecompressor() |
332 | 328 |
333 with dctx.stream_reader(b'foo') as reader: | 329 with dctx.stream_reader(b'foo') as reader: |
330 self.assertFalse(reader.closed) | |
334 self.assertTrue(reader.readable()) | 331 self.assertTrue(reader.readable()) |
335 self.assertFalse(reader.writable()) | 332 self.assertFalse(reader.writable()) |
336 self.assertTrue(reader.seekable()) | 333 self.assertTrue(reader.seekable()) |
337 self.assertFalse(reader.isatty()) | 334 self.assertFalse(reader.isatty()) |
335 self.assertFalse(reader.closed) | |
338 self.assertIsNone(reader.flush()) | 336 self.assertIsNone(reader.flush()) |
337 self.assertFalse(reader.closed) | |
338 | |
339 self.assertTrue(reader.closed) | |
339 | 340 |
340 def test_read_closed(self): | 341 def test_read_closed(self): |
341 dctx = zstd.ZstdDecompressor() | 342 dctx = zstd.ZstdDecompressor() |
342 | 343 |
343 with dctx.stream_reader(b'foo') as reader: | 344 with dctx.stream_reader(b'foo') as reader: |
344 reader.close() | 345 reader.close() |
346 self.assertTrue(reader.closed) | |
345 with self.assertRaisesRegexp(ValueError, 'stream is closed'): | 347 with self.assertRaisesRegexp(ValueError, 'stream is closed'): |
346 reader.read(1) | 348 reader.read(1) |
347 | 349 |
348 def test_bad_read_size(self): | 350 def test_bad_read_size(self): |
349 dctx = zstd.ZstdDecompressor() | 351 dctx = zstd.ZstdDecompressor() |
370 result = reader.read(8192) | 372 result = reader.read(8192) |
371 self.assertEqual(result, source) | 373 self.assertEqual(result, source) |
372 self.assertEqual(reader.tell(), len(source)) | 374 self.assertEqual(reader.tell(), len(source)) |
373 | 375 |
374 # Read after EOF should return empty bytes. | 376 # Read after EOF should return empty bytes. |
375 self.assertEqual(reader.read(), b'') | 377 self.assertEqual(reader.read(1), b'') |
376 self.assertEqual(reader.tell(), len(result)) | 378 self.assertEqual(reader.tell(), len(result)) |
377 | 379 |
378 self.assertTrue(reader.closed()) | 380 self.assertTrue(reader.closed) |
379 | 381 |
380 def test_read_buffer_small_chunks(self): | 382 def test_read_buffer_small_chunks(self): |
381 cctx = zstd.ZstdCompressor() | 383 cctx = zstd.ZstdCompressor() |
382 source = b''.join([b'foo' * 60, b'bar' * 60, b'baz' * 60]) | 384 source = b''.join([b'foo' * 60, b'bar' * 60, b'baz' * 60]) |
383 frame = cctx.compress(source) | 385 frame = cctx.compress(source) |
406 self.assertEqual(reader.tell(), 0) | 408 self.assertEqual(reader.tell(), 0) |
407 | 409 |
408 chunk = reader.read(8192) | 410 chunk = reader.read(8192) |
409 self.assertEqual(chunk, source) | 411 self.assertEqual(chunk, source) |
410 self.assertEqual(reader.tell(), len(source)) | 412 self.assertEqual(reader.tell(), len(source)) |
411 self.assertEqual(reader.read(), b'') | 413 self.assertEqual(reader.read(1), b'') |
412 self.assertEqual(reader.tell(), len(source)) | 414 self.assertEqual(reader.tell(), len(source)) |
415 self.assertFalse(reader.closed) | |
416 | |
417 self.assertTrue(reader.closed) | |
413 | 418 |
414 def test_read_stream_small_chunks(self): | 419 def test_read_stream_small_chunks(self): |
415 cctx = zstd.ZstdCompressor() | 420 cctx = zstd.ZstdCompressor() |
416 source = b''.join([b'foo' * 60, b'bar' * 60, b'baz' * 60]) | 421 source = b''.join([b'foo' * 60, b'bar' * 60, b'baz' * 60]) |
417 frame = cctx.compress(source) | 422 frame = cctx.compress(source) |
438 | 443 |
439 with dctx.stream_reader(frame) as reader: | 444 with dctx.stream_reader(frame) as reader: |
440 while reader.read(16): | 445 while reader.read(16): |
441 pass | 446 pass |
442 | 447 |
443 with self.assertRaisesRegexp(zstd.ZstdError, 'read\(\) must be called from an active'): | 448 self.assertTrue(reader.closed) |
449 | |
450 with self.assertRaisesRegexp(ValueError, 'stream is closed'): | |
444 reader.read(10) | 451 reader.read(10) |
445 | 452 |
446 def test_illegal_seeks(self): | 453 def test_illegal_seeks(self): |
447 cctx = zstd.ZstdCompressor() | 454 cctx = zstd.ZstdCompressor() |
448 frame = cctx.compress(b'foo' * 60) | 455 frame = cctx.compress(b'foo' * 60) |
472 reader.close() | 479 reader.close() |
473 | 480 |
474 with self.assertRaisesRegexp(ValueError, 'stream is closed'): | 481 with self.assertRaisesRegexp(ValueError, 'stream is closed'): |
475 reader.seek(4, os.SEEK_SET) | 482 reader.seek(4, os.SEEK_SET) |
476 | 483 |
477 with self.assertRaisesRegexp( | 484 with self.assertRaisesRegexp(ValueError, 'stream is closed'): |
478 zstd.ZstdError, 'seek\(\) must be called from an active context'): | |
479 reader.seek(0) | 485 reader.seek(0) |
480 | 486 |
481 def test_seek(self): | 487 def test_seek(self): |
482 source = b'foobar' * 60 | 488 source = b'foobar' * 60 |
483 cctx = zstd.ZstdCompressor() | 489 cctx = zstd.ZstdCompressor() |
489 reader.seek(3) | 495 reader.seek(3) |
490 self.assertEqual(reader.read(3), b'bar') | 496 self.assertEqual(reader.read(3), b'bar') |
491 | 497 |
492 reader.seek(4, os.SEEK_CUR) | 498 reader.seek(4, os.SEEK_CUR) |
493 self.assertEqual(reader.read(2), b'ar') | 499 self.assertEqual(reader.read(2), b'ar') |
500 | |
501 def test_no_context_manager(self): | |
502 source = b'foobar' * 60 | |
503 cctx = zstd.ZstdCompressor() | |
504 frame = cctx.compress(source) | |
505 | |
506 dctx = zstd.ZstdDecompressor() | |
507 reader = dctx.stream_reader(frame) | |
508 | |
509 self.assertEqual(reader.read(6), b'foobar') | |
510 self.assertEqual(reader.read(18), b'foobar' * 3) | |
511 self.assertFalse(reader.closed) | |
512 | |
513 # Calling close prevents subsequent use. | |
514 reader.close() | |
515 self.assertTrue(reader.closed) | |
516 | |
517 with self.assertRaisesRegexp(ValueError, 'stream is closed'): | |
518 reader.read(6) | |
519 | |
520 def test_read_after_error(self): | |
521 source = io.BytesIO(b'') | |
522 dctx = zstd.ZstdDecompressor() | |
523 | |
524 reader = dctx.stream_reader(source) | |
525 | |
526 with reader: | |
527 with self.assertRaises(TypeError): | |
528 reader.read() | |
529 | |
530 with reader: | |
531 with self.assertRaisesRegexp(ValueError, 'stream is closed'): | |
532 reader.read(100) | |
494 | 533 |
495 | 534 |
496 @make_cffi | 535 @make_cffi |
497 class TestDecompressor_decompressobj(unittest.TestCase): | 536 class TestDecompressor_decompressobj(unittest.TestCase): |
498 def test_simple(self): | 537 def test_simple(self): |