diff --git a/Lib/test/test_lzma.py b/Lib/test/test_lzma.py index fff261d890e..c7f2662ab0b 100644 --- a/Lib/test/test_lzma.py +++ b/Lib/test/test_lzma.py @@ -143,7 +143,6 @@ def test_decompressor_chunks(self): self.assertTrue(lzd.eof) self.assertEqual(lzd.unused_data, b"") - @unittest.expectedFailure # TODO: RUSTPYTHON; EOFError: End of stream already reached def test_decompressor_chunks_empty(self): lzd = LZMADecompressor() out = [] diff --git a/crates/common/src/compression/bz2.rs b/crates/common/src/compression/bz2.rs index d346ce4bd9c..3287a549603 100644 --- a/crates/common/src/compression/bz2.rs +++ b/crates/common/src/compression/bz2.rs @@ -312,6 +312,23 @@ mod tests { assert!(decompressor.eof()); } + #[test] + fn empty_input_does_not_finish_a_stream() { + let mut compressor = Compressor::new(9).unwrap(); + let mut encoded = compressor.compress(b"later input").unwrap(); + encoded.extend(compressor.flush().unwrap()); + + let mut decompressor = Decompressor::new(); + assert_eq!(decompressor.decompress(b"", None).unwrap(), b""); + assert!(!decompressor.eof()); + assert!(decompressor.needs_input()); + assert_eq!( + decompressor.decompress(&encoded, None).unwrap(), + b"later input" + ); + assert!(decompressor.eof()); + } + #[test] fn bad_data_latches_failure() { let mut decompressor = Decompressor::new(); diff --git a/crates/common/src/compression/lzma.rs b/crates/common/src/compression/lzma.rs index 79262fc0dc8..2e2b44fd984 100644 --- a/crates/common/src/compression/lzma.rs +++ b/crates/common/src/compression/lzma.rs @@ -378,8 +378,10 @@ fn decompress_chunks( stream: &mut LzmaStream, max_length: Option, ) -> Result<(Vec, bool), XzError> { + // No input to feed the decoder: not a stream end, so `eof` stays false and + // the caller can still supply compressed data later. if chunks.is_empty() { - return Ok((Vec::new(), true)); + return Ok((Vec::new(), false)); } let max_length = max_length.unwrap_or(usize::MAX); let mut output = Vec::new(); @@ -622,6 +624,21 @@ impl Compressor { mod tests { use super::*; + #[test] + fn empty_input_does_not_finish_a_stream() { + let mut compressor = Compressor::new(FORMAT_XZ, CHECK_CRC64, PRESET_DEFAULT, None).unwrap(); + let mut encoded = compressor.compress(b"data").unwrap(); + encoded.extend(compressor.flush().unwrap()); + + let mut decompressor = Decompressor::new(FORMAT_AUTO, None, None).unwrap(); + assert_eq!(decompressor.decompress(b"", None).unwrap(), b""); + assert!(!decompressor.eof()); + assert!(decompressor.needs_input()); + + assert_eq!(decompressor.decompress(&encoded, None).unwrap(), b"data"); + assert!(decompressor.eof()); + } + #[test] fn encode_lzma1_properties_rejects_invalid_lclppb() { for (lc, lp, pb) in [(5, 0, 0), (0, 5, 0), (4, 1, 0), (0, 0, 5)] {