Skip to content

Commit e4429c4

Browse files
authored
Add unit tests of the different flush kinds (#498)
This PR adds tests of the various flush kinds to ensure that all backends implement them consistently. The cases are carefully constructed so that even quite different backend implementations are likely to produce the expected output. In particular, it counts on the encoder detecting when the input is/isn't compressible and writing either compressed or stored blocks accordingly. This also corrects miniz_oxide to use partial fushes when requested.
2 parents 517ad87 + 622f1e9 commit e4429c4

2 files changed

Lines changed: 64 additions & 2 deletions

File tree

src/ffi/miniz_oxide.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,8 @@ impl From<FlushCompress> for MZFlush {
136136
fn from(value: FlushCompress) -> Self {
137137
match value {
138138
FlushCompress::None => Self::None,
139-
FlushCompress::Partial | FlushCompress::Sync => Self::Sync,
139+
FlushCompress::Partial => Self::Partial,
140+
FlushCompress::Sync => Self::Sync,
140141
FlushCompress::Full => Self::Full,
141142
FlushCompress::Finish => Self::Finish,
142143
}

src/mem.rs

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -663,7 +663,6 @@ mod tests {
663663
use crate::write;
664664
use crate::{Compression, Decompress, FlushDecompress};
665665

666-
#[cfg(feature = "any_zlib")]
667666
use crate::{Compress, FlushCompress};
668667

669668
#[test]
@@ -762,4 +761,66 @@ mod tests {
762761

763762
assert_eq!(err.message(), Some("invalid stored block lengths"));
764763
}
764+
765+
fn compress_with_flush(flush: FlushCompress) -> Vec<u8> {
766+
let incompressible = (0..=255).collect::<Vec<u8>>();
767+
let mut output = vec![0; 1024];
768+
769+
// Feed in the incompressible data followed by the indicated flush type.
770+
let mut w = Compress::new(Compression::default(), false);
771+
w.compress(&incompressible, &mut output, flush).unwrap();
772+
773+
if flush != FlushCompress::None {
774+
// The first instance of incompressible input should have been written uncompressed.
775+
assert!(w.total_out() >= 261);
776+
assert_eq!(&output[0..5], &[0, 0, 1, 0xff, !1]);
777+
assert_eq!(&output[5..261], &incompressible);
778+
}
779+
780+
// Feed in the same data again.
781+
let len = w.total_out() as usize;
782+
w.compress(&incompressible, &mut output[len..], FlushCompress::Finish)
783+
.unwrap();
784+
785+
if flush != FlushCompress::Full {
786+
// This time, the data should have been compressed (because it is an exact duplicate of
787+
// the earlier block).
788+
assert!(w.total_out() < 300);
789+
}
790+
791+
// Assert that all input has been processed.
792+
assert_eq!(w.total_in(), 256 * 2);
793+
794+
output.resize(w.total_out() as usize, 0);
795+
output
796+
}
797+
798+
#[test]
799+
fn test_partial_flush() {
800+
let output = compress_with_flush(FlushCompress::Partial);
801+
802+
// Check for partial flush marker.
803+
assert_eq!(output[261], 0x2);
804+
assert_eq!(output[262] & 0x7, 0x4);
805+
}
806+
807+
#[test]
808+
fn test_sync_flush() {
809+
let output = compress_with_flush(FlushCompress::Sync);
810+
811+
// Check for sync flush marker.
812+
assert_eq!(&output[261..][..5], &[0, 0, 0, 0xff, 0xff]);
813+
}
814+
815+
#[test]
816+
fn test_full_flush() {
817+
let output = compress_with_flush(FlushCompress::Full);
818+
assert_eq!(output.len(), 527);
819+
820+
// Check for sync flush marker.
821+
assert_eq!(&output[261..][..5], &[0, 0, 0, 0xff, 0xff]);
822+
823+
// Check that the second instance of incompressible input was also written uncompressed.
824+
assert_eq!(&output[266..][..5], &[1, 0, 1, 0xff, !1]);
825+
}
765826
}

0 commit comments

Comments
 (0)