#![cfg(test)]
#![allow(non_upper_case_globals)]
#![allow(dead_code)]
extern crate core;
extern crate brotli_decompressor;
use super::HeapAllocator;
#[allow(unused_imports)]
use super::alloc_no_stdlib::{Allocator, SliceWrapper, SliceWrapperMut};
use super::brotli::BrotliResult;
use super::brotli::BrotliState;
use super::Rebox;
#[cfg(feature="std")]
use super::brotli::{CompressorReader, CompressorWriter};
#[cfg(feature="std")]
use super::brotli_decompressor::{Decompressor, DecompressorWriter};
use core::cmp;
use std::io;
#[cfg(feature="std")]
use std::io::{Read, Write};
use std::time::Duration;
#[cfg(not(feature="disable-timer"))]
use std::time::SystemTime;
use brotli::BrotliDecompressStream;
#[cfg(feature="benchmark")]
extern crate test;
#[cfg(feature="benchmark")]
use self::test::Bencher;
pub struct Buffer {
data: Vec<u8>,
read_offset: usize,
}
pub struct UnlimitedBuffer {
data: Vec<u8>,
read_offset: usize,
}
#[cfg(feature="disable-timer")]
fn now() -> Duration {
return Duration::new(0, 0);
}
#[cfg(not(feature="disable-timer"))]
fn now() -> SystemTime {
return SystemTime::now();
}
#[cfg(not(feature="disable-timer"))]
fn elapsed(start: SystemTime) -> (Duration, bool) {
match start.elapsed() {
Ok(delta) => return (delta, false),
_ => return (Duration::new(0, 0), true),
}
}
#[cfg(feature="disable-timer")]
fn elapsed(_start: Duration) -> (Duration, bool) {
return (Duration::new(0, 0), true);
}
fn _write_all<OutputType>(w: &mut OutputType, buf: &[u8]) -> Result<(), io::Error>
where OutputType: io::Write
{
let mut total_written: usize = 0;
while total_written < buf.len() {
match w.write(&buf[total_written..]) {
Err(e) => {
match e.kind() {
io::ErrorKind::Interrupted => continue,
_ => return Err(e),
}
}
Ok(cur_written) => {
if cur_written == 0 {
return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "Write EOF"));
}
total_written += cur_written;
}
}
}
Ok(())
}
trait Runner {
fn iter<Fn:FnMut()> (&mut self, cb: &mut Fn);
}
struct Passthrough {
}
impl Runner for Passthrough {
fn iter<Fn:FnMut()> (&mut self, cb: &mut Fn) {
cb()
}
}
#[cfg(feature="benchmark")]
struct BenchmarkPassthrough<'a> (pub &'a mut Bencher);
#[cfg(feature="benchmark")]
impl<'a> Runner for BenchmarkPassthrough<'a>{
fn iter<Fn:FnMut()> (&mut self, cb: &mut Fn) {
self.0.iter(cb)
}
}
fn decompress_internal<InputType, OutputType, Run: Runner>(r: &mut InputType,
mut w: &mut OutputType,
input_buffer_limit: usize,
output_buffer_limit: usize,
runner: &mut Run)
-> Result<(), io::Error>
where InputType: io::Read,
OutputType: io::Write
{
let mut total = Duration::new(0, 0);
let mut range: usize = 0;
let mut timing_error: bool = false;
runner.iter(&mut || {
range += 1;
let mut brotli_state =
BrotliState::new(HeapAllocator::default(),
HeapAllocator::default(),
HeapAllocator::default());
let mut input = brotli_state.alloc_u8.alloc_cell(input_buffer_limit);
let mut output = brotli_state.alloc_u8.alloc_cell(output_buffer_limit);
let mut available_out: usize = output.slice().len();
let mut available_in: usize = 0;
let mut input_offset: usize = 0;
let mut output_offset: usize = 0;
let mut result: BrotliResult = BrotliResult::NeedsMoreInput;
loop {
match result {
BrotliResult::NeedsMoreInput => {
input_offset = 0;
match r.read(input.slice_mut()) {
Err(e) => {
match e.kind() {
io::ErrorKind::Interrupted => continue,
_ => panic!(e),
}
}
Ok(size) => {
if size == 0 {
panic!(io::Error::new(io::ErrorKind::UnexpectedEof, "Read EOF"));
}
available_in = size;
}
}
}
BrotliResult::NeedsMoreOutput => {
_write_all(&mut w, &output.slice()[..output_offset]).unwrap();
output_offset = 0;
}
BrotliResult::ResultSuccess => break,
BrotliResult::ResultFailure => panic!("FAILURE"),
}
let mut written: usize = 0;
let start = now();
result = BrotliDecompressStream(&mut available_in,
&mut input_offset,
&input.slice(),
&mut available_out,
&mut output_offset,
&mut output.slice_mut(),
&mut written,
&mut brotli_state);
let (delta, err) = elapsed(start);
if err {
timing_error = true;
}
total = total + delta;
if output_offset != 0 {
_write_all(&mut w, &output.slice()[..output_offset]).unwrap();
output_offset = 0;
available_out = output.slice().len()
}
}
brotli_state.BrotliStateCleanup();
});
if timing_error {
let _r = super::writeln0(&mut io::stderr(), "Timing error");
} else {
let _r = super::writeln_time(&mut io::stderr(),
"Iterations; Time",
range as u64,
total.as_secs(),
total.subsec_nanos());
}
Ok(())
}
impl Buffer {
pub fn new(buf: &[u8]) -> Buffer {
let mut ret = Buffer {
data: Vec::<u8>::new(),
read_offset: 0,
};
ret.data.extend(buf);
return ret;
}
}
impl UnlimitedBuffer {
pub fn new(buf: &[u8]) -> Self {
let mut ret = UnlimitedBuffer {
data: Vec::<u8>::new(),
read_offset: 0,
};
ret.data.extend(buf);
return ret;
}
pub fn reset_read(&mut self) {
self.read_offset = 0;
}
pub fn data(&self) -> &[u8] {
&self.data[..]
}
}
impl io::Read for Buffer {
fn read(self: &mut Self, buf: &mut [u8]) -> io::Result<usize> {
if self.read_offset == self.data.len() {
self.read_offset = 0;
}
let bytes_to_read = cmp::min(buf.len(), self.data.len() - self.read_offset);
if bytes_to_read > 0 {
buf[0..bytes_to_read].clone_from_slice(&self.data[self.read_offset..
self.read_offset + bytes_to_read]);
}
self.read_offset += bytes_to_read;
return Ok(bytes_to_read);
}
}
impl io::Write for Buffer {
fn write(self: &mut Self, buf: &[u8]) -> io::Result<usize> {
if self.read_offset == self.data.len() {
return Ok(buf.len());
}
self.data.extend(buf);
return Ok(buf.len());
}
fn flush(self: &mut Self) -> io::Result<()> {
return Ok(());
}
}
impl io::Read for UnlimitedBuffer {
fn read(self: &mut Self, buf: &mut [u8]) -> io::Result<usize> {
let bytes_to_read = cmp::min(buf.len(), self.data.len() - self.read_offset);
if bytes_to_read > 0 {
buf[0..bytes_to_read].clone_from_slice(&self.data[self.read_offset..
self.read_offset + bytes_to_read]);
}
self.read_offset += bytes_to_read;
return Ok(bytes_to_read);
}
}
impl io::Write for UnlimitedBuffer {
fn write(self: &mut Self, buf: &[u8]) -> io::Result<usize> {
self.data.extend(buf);
return Ok(buf.len());
}
fn flush(self: &mut Self) -> io::Result<()> {
return Ok(());
}
}
#[allow(non_snake_case)]
#[test]
fn test_roundtrip_64x() {
let X = 'X' as u8;
let in_buf: [u8; 64] = [X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X];
let mut input = UnlimitedBuffer::new(&in_buf);
let mut compressed = UnlimitedBuffer::new(&[]);
let mut output = UnlimitedBuffer::new(&[]);
let q: i32 = 9;
let lgwin: i32 = 16;
let mut params = super::brotli::enc::BrotliEncoderInitParams();
params.quality = q;
params.lgwin = lgwin;
match super::compress(&mut input, &mut compressed, 65536, ¶ms, &[], 1) {
Ok(_) => {}
Err(e) => panic!("Error {:?}", e),
}
let mut compressed_in = UnlimitedBuffer::new(&compressed.data[..]);
match super::decompress(&mut compressed_in, &mut output, 65536, Rebox::default()) {
Ok(_) => {}
Err(e) => panic!("Error {:?}", e),
}
for i in 0..input.data.len() {
assert_eq!(output.data[i], input.data[i]);
}
assert_eq!(output.data.len(), input.data.len());
assert_eq!(input.read_offset, in_buf.len());
}
fn roundtrip_helper(in_buf: &[u8], q: i32, lgwin: i32, q9_5: bool) -> usize {
let mut params = super::brotli::enc::BrotliEncoderInitParams();
params.quality = q;
params.q9_5 = q9_5;
params.lgwin = lgwin;
params.size_hint = if in_buf.len() > 100000 { 2048 * 1024} else {in_buf.len()};
let mut input = UnlimitedBuffer::new(&in_buf);
let mut compressed = UnlimitedBuffer::new(&[]);
let mut output = UnlimitedBuffer::new(&[]);
match super::compress(&mut input, &mut compressed, 4096, ¶ms, &[], 1) {
Ok(_) => {}
Err(e) => panic!("Error {:?}", e),
}
let mut compressed_in = UnlimitedBuffer::new(&compressed.data[..]);
match super::decompress(&mut compressed_in, &mut output, 4096, Rebox::default()) {
Ok(_) => {}
Err(e) => panic!("Error {:?}", e),
}
for i in 0..input.data.len() {
assert_eq!(output.data[i], input.data[i]);
}
assert_eq!(output.data.len(), input.data.len());
assert_eq!(input.read_offset, in_buf.len());
return compressed.data[..].len()
}
fn total_roundtrip_helper(data: &[u8]) {
for q in 0..10 {
roundtrip_helper(data, q as i32, (q + 13) as i32, false);
}
roundtrip_helper(data, 10, 23, true);
}
static RANDOM_THEN_UNICODE : &'static [u8] = include_bytes!("../../testdata/random_then_unicode");
#[test]
fn test_random_then_unicode_0() {
roundtrip_helper(RANDOM_THEN_UNICODE, 0, 13, false);
}
#[test]
fn test_random_then_unicode_1() {
roundtrip_helper(RANDOM_THEN_UNICODE, 1, 14, false);
}
#[test]
fn test_random_then_unicode_2() {
roundtrip_helper(RANDOM_THEN_UNICODE, 2, 15, false);
}
#[test]
fn test_random_then_unicode_3() {
roundtrip_helper(RANDOM_THEN_UNICODE, 3, 16, false);
}
#[test]
fn test_random_then_unicode_4() {
roundtrip_helper(RANDOM_THEN_UNICODE, 4, 17, false);
}
#[test]
fn test_random_then_unicode_5() {
roundtrip_helper(RANDOM_THEN_UNICODE, 5, 18, false);
}
#[test]
fn test_random_then_unicode_6() {
roundtrip_helper(RANDOM_THEN_UNICODE, 6, 19, false);
}
#[test]
fn test_random_then_unicode_7() {
roundtrip_helper(RANDOM_THEN_UNICODE, 7, 20, false);
}
#[test]
fn test_random_then_unicode_8() {
roundtrip_helper(RANDOM_THEN_UNICODE, 8, 21, false);
}
#[test]
fn test_random_then_unicode_9() {
roundtrip_helper(RANDOM_THEN_UNICODE, 9, 22, false);
}
#[cfg(feature="std")]
const random_then_unicode_compressed_size_9_5 : usize = 136563;
#[cfg(feature="std")]
const random_then_unicode_compressed_size_9_5x : usize = 136045;
#[cfg(not(feature="std"))]
const alice_compressed_size_10 : usize = 47490;
#[cfg(not(feature="std"))]
const alice_compressed_size_11 : usize = 46496;
#[cfg(feature="std")]
#[cfg(not(feature="float64"))]
const alice_compressed_size_10 : usize = 47488;
#[cfg(feature="std")]
#[cfg(not(feature="float64"))]
const alice_compressed_size_11 : usize = 46493;
#[cfg(feature="std")]
#[cfg(feature="float64")]
const alice_compressed_size_10 : usize = 47515;
#[cfg(feature="std")]
#[cfg(feature="float64")]
const alice_compressed_size_11 : usize = 46510;
#[cfg(not(feature="std"))] const random_then_unicode_compressed_size_9_5 : usize = 136719;
#[cfg(not(feature="std"))] const random_then_unicode_compressed_size_9_5x : usize = 136095;
#[test]
fn test_random_then_unicode_9_5() {
let c_size = roundtrip_helper(RANDOM_THEN_UNICODE, 10, 28, true);
assert_eq!(c_size, random_then_unicode_compressed_size_9_5);
}
#[test]
fn test_random_then_unicode_9x5() {
let c_size = roundtrip_helper(RANDOM_THEN_UNICODE, 11, 22, true);
assert_eq!(c_size, random_then_unicode_compressed_size_9_5x);
}
#[test]
fn test_alice29_11() {
let c_size = roundtrip_helper(include_bytes!("../../testdata/alice29.txt"), 11, 22, false);
if c_size != 46492 { assert_eq!(c_size, alice_compressed_size_11);
}
}
#[test]
fn test_alice29_10() {
let c_size = roundtrip_helper(include_bytes!("../../testdata/alice29.txt"), 10, 22, false);
assert_eq!(c_size, alice_compressed_size_10);
}
#[test]
fn test_roundtrip_quickfox_repeated() {
total_roundtrip_helper(include_bytes!("../../testdata/quickfox_repeated"));
}
#[test]
fn test_roundtrip_alice29() {
total_roundtrip_helper(include_bytes!("../../testdata/alice29.txt"));
}
#[test]
fn test_roundtrip_as_you_lik() {
total_roundtrip_helper(include_bytes!("../../testdata/asyoulik.txt"));
}
#[cfg(feature="std")]
fn reader_helper(mut in_buf: &[u8], q: u32, lgwin: u32) {
let original_buf = in_buf;
let mut cmp = [0u8; 259];
let mut input = UnlimitedBuffer::new(&in_buf);
{
let renc = CompressorReader::new(&mut input, 255, q, lgwin);
let mut rdec = Decompressor::new(renc, 257);
loop {
match rdec.read(&mut cmp[..]) {
Ok(size) => {
if size == 0 {
break;
}
assert_eq!(cmp[..size], in_buf[..size]);
in_buf = &in_buf[size..];
}
Err(e) => panic!("Error {:?}", e),
}
}
}
in_buf = original_buf;
input = UnlimitedBuffer::new(&in_buf);
let mut r2enc = CompressorReader::new(&mut input, 255, q, lgwin);
let mut compressed_size = 0usize;
loop {
match r2enc.read(&mut cmp[..]) {
Ok(size) => {
if size == 0 {
break;
}
compressed_size += size;
}
Err(e) => panic!("Error {:?}", e),
}
}
let pct_ratio = 90usize;
assert!(compressed_size < original_buf.len() * pct_ratio / 100);
}
#[cfg(feature="std")]
#[test]
fn test_reader_64x() {
reader_helper(include_bytes!("../../testdata/64x"), 9, 20);
}
#[cfg(feature="std")]
#[test]
fn test_reader_as_you_lik() {
reader_helper(include_bytes!("../../testdata/asyoulik.txt"), 9, 20);
}
#[cfg(feature="std")]
#[test]
fn test_reader_quickfox_repeated() {
reader_helper(include_bytes!("../../testdata/quickfox_repeated"), 9, 20);
}
#[cfg(feature="std")]
#[test]
fn test_reader_random_then_unicode() {
reader_helper(include_bytes!("../../testdata/random_then_unicode"), 9, 20);
}
#[cfg(feature="std")]
#[test]
fn test_reader_alice() {
reader_helper(include_bytes!("../../testdata/alice29.txt"), 9, 22);
}
#[cfg(feature="std")]
fn writer_helper(mut in_buf: &[u8], buf_size: usize, q: u32, lgwin: u32, do_flush: bool) {
let original_buf = in_buf;
let mut output = UnlimitedBuffer::new(&[]);
{
{let wdec = DecompressorWriter::new(&mut output, 257);
{let mut wenc = CompressorWriter::new(wdec, 255, q, lgwin);
while in_buf.len() > 0 {
match wenc.write(&in_buf[..cmp::min(in_buf.len(), buf_size)]) {
Ok(size) => {
if size == 0 {
break;
}
in_buf = &in_buf[size..];
}
Err(e) => panic!("Error {:?}", e),
}
if do_flush {
if let Err(e) = wenc.flush() {
panic!("Error {:?}", e);
}
}
}
}
}
assert_eq!(output.data.len(), original_buf.len());
for i in 0..cmp::min(original_buf.len(), output.data.len()) {
assert_eq!(output.data[i], original_buf[i]);
}
in_buf = original_buf;
let mut compressed = UnlimitedBuffer::new(&[]);
{
let mut wenc = CompressorWriter::new(&mut compressed, 255, q, lgwin);
while in_buf.len() > 0 {
match wenc.write(&in_buf[..cmp::min(in_buf.len(), buf_size)]) {
Ok(size) => {
if size == 0 {
break;
}
in_buf = &in_buf[size..];
}
Err(e) => panic!("Error {:?}", e),
}
}
}
let pct_ratio = 90usize;
assert!(compressed.data.len() < original_buf.len() * pct_ratio / 100);
}
}
#[cfg(feature="std")]
#[test]
fn test_writer_as_you_lik() {
writer_helper(include_bytes!("../../testdata/asyoulik.txt"), 17, 9, 20, false);
}
#[cfg(feature="std")]
#[test]
fn test_writer_64x() {
writer_helper(include_bytes!("../../testdata/64x"), 17, 9, 20, false);
}
#[cfg(feature="std")]
#[test]
fn test_writer_quickfox_repeated() {
writer_helper(include_bytes!("../../testdata/quickfox_repeated"), 251, 9, 20, false);
}
#[cfg(feature="std")]
#[test]
fn test_writer_random_then_unicode() {
writer_helper(include_bytes!("../../testdata/random_then_unicode"), 277, 9, 20, false);
}
#[cfg(feature="std")]
#[test]
fn test_writer_alice() {
writer_helper(include_bytes!("../../testdata/alice29.txt"), 299, 9, 22, true);
}
#[test]
fn test_10x_10y() {
let in_buf: [u8; 12] = [0x1b, 0x13, 0x00, 0x00, 0xa4, 0xb0, 0xb2, 0xea, 0x81, 0x47, 0x02, 0x8a];
let mut input = Buffer::new(&in_buf);
let mut output = Buffer::new(&[]);
output.read_offset = 20;
match super::decompress(&mut input, &mut output, 65536, Rebox::default()) {
Ok(_) => {}
Err(e) => panic!("Error {:?}", e),
}
let mut i: usize = 0;
while i < 10 {
assert_eq!(output.data[i], 'X' as u8);
assert_eq!(output.data[i + 10], 'Y' as u8);
i += 1;
}
assert_eq!(output.data.len(), 20);
assert_eq!(input.read_offset, in_buf.len());
}
#[test]
fn test_10x_10y_one_out_byte() {
let in_buf: [u8; 12] = [0x1b, 0x13, 0x00, 0x00, 0xa4, 0xb0, 0xb2, 0xea, 0x81, 0x47, 0x02, 0x8a];
let mut input = Buffer::new(&in_buf);
let mut output = Buffer::new(&[]);
output.read_offset = 20;
match decompress_internal(&mut input, &mut output, 12, 1, &mut Passthrough{}) {
Ok(_) => {}
Err(e) => panic!("Error {:?}", e),
}
let mut i: usize = 0;
while i < 10 {
assert_eq!(output.data[i], 'X' as u8);
assert_eq!(output.data[i + 10], 'Y' as u8);
i += 1;
}
assert_eq!(output.data.len(), 20);
assert_eq!(input.read_offset, in_buf.len());
}
#[test]
fn test_10x_10y_byte_by_byte() {
let in_buf: [u8; 12] = [0x1b, 0x13, 0x00, 0x00, 0xa4, 0xb0, 0xb2, 0xea, 0x81, 0x47, 0x02, 0x8a];
let mut input = Buffer::new(&in_buf);
let mut output = Buffer::new(&[]);
output.read_offset = 20;
match decompress_internal(&mut input, &mut output, 1, 1, &mut Passthrough{}) {
Ok(_) => {}
Err(e) => panic!("Error {:?}", e),
}
let mut i: usize = 0;
while i < 10 {
assert_eq!(output.data[i], 'X' as u8);
assert_eq!(output.data[i + 10], 'Y' as u8);
i += 1;
}
assert_eq!(output.data.len(), 20);
assert_eq!(input.read_offset, in_buf.len());
}
fn assert_decompressed_input_matches_output(input_slice: &[u8],
output_slice: &[u8],
input_buffer_size: usize,
output_buffer_size: usize) {
let mut input = Buffer::new(input_slice);
let mut output = Buffer::new(&[]);
output.read_offset = output_slice.len();
if input_buffer_size == output_buffer_size {
match super::decompress(&mut input, &mut output, input_buffer_size, Rebox::default()) {
Ok(_) => {}
Err(e) => panic!("Error {:?}", e),
}
} else {
match decompress_internal(&mut input,
&mut output,
input_buffer_size,
output_buffer_size,
&mut Passthrough{}) {
Ok(_) => {}
Err(e) => panic!("Error {:?}", e),
}
}
assert_eq!(output.data.len(), output_slice.len());
assert_eq!(output.data, output_slice)
}
#[cfg(feature="benchmark")]
fn benchmark_decompressed_input(input_slice: &[u8],
output_slice: &[u8],
input_buffer_size: usize,
output_buffer_size: usize,
bench: &mut Bencher) {
let mut input = Buffer::new(input_slice);
let mut output = Buffer::new(&[]);
output.read_offset = output_slice.len();
match decompress_internal(&mut input,
&mut output,
input_buffer_size,
output_buffer_size,
&mut BenchmarkPassthrough(bench),
) {
Ok(_) => {}
Err(e) => panic!("Error {:?}", e),
}
assert_eq!(output.data.len(), output_slice.len());
assert_eq!(output.data, output_slice)
}
pub struct LimitedBuffer<'a> {
pub data: &'a mut [u8],
pub write_offset: usize,
pub read_offset: usize,
}
impl<'a> LimitedBuffer<'a> {
pub fn new(buf: &'a mut [u8]) -> Self {
LimitedBuffer {
data: buf,
write_offset: 0,
read_offset: 0,
}
}
}
impl<'a> LimitedBuffer<'a> {
fn reset(&mut self) {
self.write_offset = 0;
self.read_offset = 0;
self.data.split_at_mut(32).0.clone_from_slice(&[0u8;32]); }
fn reset_read(&mut self) {
self.read_offset = 0;
}
fn written(&self) -> &[u8] {
&self.data[..self.write_offset]
}
}
impl<'a> io::Read for LimitedBuffer<'a> {
fn read(self: &mut Self, buf: &mut [u8]) -> io::Result<usize> {
let bytes_to_read = cmp::min(buf.len(), self.data.len() - self.read_offset);
if bytes_to_read > 0 {
buf[0..bytes_to_read].clone_from_slice(&self.data[self.read_offset..
self.read_offset + bytes_to_read]);
}
self.read_offset += bytes_to_read;
return Ok(bytes_to_read);
}
}
impl<'a> io::Write for LimitedBuffer<'a> {
fn write(self: &mut Self, buf: &[u8]) -> io::Result<usize> {
let bytes_to_write = cmp::min(buf.len(), self.data.len() - self.write_offset);
if bytes_to_write > 0 {
self.data[self.write_offset..self.write_offset + bytes_to_write].clone_from_slice(
&buf[..bytes_to_write]);
} else {
return Err(io::Error::new(io::ErrorKind::WriteZero, "OutOfBufferSpace"));
}
self.write_offset += bytes_to_write;
Ok(bytes_to_write)
}
fn flush(self: &mut Self) -> io::Result<()> {
return Ok(());
}
}
fn benchmark_helper<Run: Runner>(input_slice: &[u8],
compress_buffer_size: usize,
decompress_buffer_size: usize,
bench_compress: bool,
bench_decompress: bool,
bench: &mut Run,
quality: i32,
q9_5: bool,
) {
let mut params = super::brotli::enc::BrotliEncoderInitParams();
params.quality = quality;
params.q9_5 = q9_5;
params.large_window= true;
let mut input = UnlimitedBuffer::new(&input_slice[..]);
let mut compressed_array = vec![0;input_slice.len() * 100/99];
let mut rt_array = vec![0;input_slice.len() + 1];
let mut compressed = LimitedBuffer::new(&mut compressed_array[..]);
let mut rt = LimitedBuffer::new(&mut rt_array[..]);
if !bench_compress {
match super::compress(&mut input, &mut compressed, compress_buffer_size, ¶ms, &[], 1) {
Ok(_) => {}
Err(e) => panic!("Error {:?}", e),
}
}
bench.iter(&mut || {
input.reset_read();
if bench_compress {
compressed.reset();
match super::compress(&mut input, &mut compressed, compress_buffer_size, ¶ms, &[], 1) {
Ok(_) => {}
Err(e) => panic!("Error {:?}", e),
}
}
if bench_decompress {
compressed.reset_read();
rt.reset();
match super::decompress(&mut compressed, &mut rt, decompress_buffer_size, Rebox::default()) {
Ok(_) => {}
Err(e) => panic!("Error {:?}", e),
}
}
});
if !bench_decompress {
compressed.reset_read();
rt.reset();
match super::decompress(&mut compressed, &mut rt, decompress_buffer_size, Rebox::default()) {
Ok(_) => {}
Err(e) => panic!("Error {:?}", e),
}
}
assert_eq!(rt.write_offset, input_slice.len());
assert_eq!(&rt.data[..input_slice.len()],
input_slice);
}
fn expand_test_data(size: usize) -> Vec<u8> {
let mut ret = vec![0u8; size];
let original_data = include_bytes!("../../testdata/random_then_unicode");
let mut count = 0;
let mut iter = 0usize;
while count < size {
let to_copy = core::cmp::min(size - count, original_data.len());
let target = &mut ret[count..(count + to_copy)];
for (dst, src) in target.iter_mut().zip(original_data[..to_copy].iter()) {
*dst = src.wrapping_add(iter as u8);
}
count += to_copy;
iter += 1;
}
ret
}
#[test]
fn test_1024k() {
let td = expand_test_data(1024 * 1024);
benchmark_helper(&td[..],
65536,
65536,
true,
true,
&mut Passthrough{},
2,
false);
}
static UKKONOOA: &'static[u8] = include_bytes!("../../testdata/ukkonooa");
#[test]
fn test_ukkonooa() {
let td = UKKONOOA;
benchmark_helper(&td[..],
65536,
65536,
true,
true,
&mut Passthrough{},
11,
false);
}
#[cfg(feature="benchmark")]
#[bench]
fn bench_e2e_decode_q9_5_1024k(bench: &mut Bencher) {
let td = expand_test_data(1024 * 1024);
benchmark_helper(&td[..],
65536,
65536,
false,
true,
&mut BenchmarkPassthrough(bench),
11,
true);
}
#[cfg(feature="benchmark")]
#[bench]
fn bench_e2e_decode_q11_1024k(bench: &mut Bencher) {
let td = expand_test_data(1024 * 1024);
benchmark_helper(&td[..],
65536,
65536,
false,
true,
&mut BenchmarkPassthrough(bench),
11,
false);
}
#[cfg(feature="benchmark")]
#[bench]
fn bench_e2e_decode_q5_1024k(bench: &mut Bencher) {
let td = expand_test_data(1024 * 1024);
benchmark_helper(&td[..],
65536,
65536,
false,
true,
&mut BenchmarkPassthrough(bench),
5,
false);
}
#[cfg(feature="benchmark")]
#[bench]
fn bench_e2e_rt_q9_5_1024k(bench: &mut Bencher) {
let td = expand_test_data(1024 * 1024);
benchmark_helper(&td[..],
65536,
65536,
true,
true,
&mut BenchmarkPassthrough(bench),
11,
true);
}
#[cfg(feature="benchmark")]
#[bench]
fn bench_e2e_rt_q11_1024k(bench: &mut Bencher) {
let td = expand_test_data(1024 * 1024);
benchmark_helper(&td[..],
65536,
65536,
true,
true,
&mut BenchmarkPassthrough(bench),
11,
false);
}
#[cfg(feature="benchmark")]
#[bench]
fn bench_e2e_rt_q9_1024k(bench: &mut Bencher) {
let td = expand_test_data(1024 * 1024);
benchmark_helper(&td[..],
65536,
65536,
true,
true,
&mut BenchmarkPassthrough(bench),
9,
false);
}
#[cfg(feature="benchmark")]
#[bench]
fn bench_e2e_rt_q5_1024k(bench: &mut Bencher) {
let td = expand_test_data(1024 * 1024);
benchmark_helper(&td[..],
65536,
65536,
true,
true,
&mut BenchmarkPassthrough(bench),
5,
false);
}
#[test]
fn test_64x() {
assert_decompressed_input_matches_output(include_bytes!("../../testdata/64x.compressed"),
include_bytes!("../../testdata/64x"),
3,
3);
}
#[test]
fn test_as_you_like_it() {
assert_decompressed_input_matches_output(include_bytes!("../../testdata/asyoulik.txt.compressed"),
include_bytes!("../../testdata/asyoulik.txt"),
65536,
65536);
}
#[test]
#[should_panic]
fn test_negative_hypothesis() {
assert_decompressed_input_matches_output(include_bytes!("../../testdata/64x"),
include_bytes!("../../testdata/64x"),
3,
3);
}
static ALICE29_BR: &'static [u8] = include_bytes!("../../testdata/alice29.txt.compressed");
static ALICE29: &'static [u8] = include_bytes!("../../testdata/alice29.txt");
#[test]
fn test_alice29() {
assert_decompressed_input_matches_output(ALICE29_BR, ALICE29, 65536, 65536);
}
#[cfg(feature="benchmark")]
#[bench]
fn benchmark_alice29(bench: &mut Bencher) {
benchmark_decompressed_input(ALICE29_BR, ALICE29, 65536, 65536, bench);
}
#[test]
fn test_alice1() {
assert_decompressed_input_matches_output(ALICE29_BR, ALICE29, 1, 65536);
}
#[test]
fn test_backward65536() {
assert_decompressed_input_matches_output(include_bytes!("../../testdata/backward65536.compressed"),
include_bytes!("../../testdata/backward65536"),
65536,
65536);
}
#[test]
fn test_compressed_file() {
assert_decompressed_input_matches_output(include_bytes!("../../testdata/compressed_file.compressed"),
include_bytes!("../../testdata/compressed_file"),
65536,
65536);
}
#[test]
fn test_compressed_repeated() {
assert_decompressed_input_matches_output(include_bytes!("../../testdata/compressed_repeated.\
compressed"),
include_bytes!("../../testdata/compressed_repeated"),
65536,
65536);
}
#[test]
fn test_empty() {
assert_decompressed_input_matches_output(include_bytes!("../../testdata/empty.compressed"),
include_bytes!("../../testdata/empty"),
65536,
65536);
}
#[test]
fn test_empty0() {
assert_decompressed_input_matches_output(include_bytes!("../../testdata/empty.compressed.00"),
include_bytes!("../../testdata/empty"),
65536,
65536);
}
#[test]
fn test_empty1() {
assert_decompressed_input_matches_output(include_bytes!("../../testdata/empty.compressed.01"),
include_bytes!("../../testdata/empty"),
65536,
65536);
}
#[test]
fn test_empty2() {
assert_decompressed_input_matches_output(include_bytes!("../../testdata/empty.compressed.02"),
include_bytes!("../../testdata/empty"),
65536,
65536);
}
#[test]
fn test_empty3() {
assert_decompressed_input_matches_output(include_bytes!("../../testdata/empty.compressed.03"),
include_bytes!("../../testdata/empty"),
65536,
65536);
}
#[test]
fn test_empty4() {
assert_decompressed_input_matches_output(include_bytes!("../../testdata/empty.compressed.04"),
include_bytes!("../../testdata/empty"),
65536,
65536);
}
#[test]
fn test_empty5() {
assert_decompressed_input_matches_output(include_bytes!("../../testdata/empty.compressed.05"),
include_bytes!("../../testdata/empty"),
65536,
65536);
}
#[test]
fn test_empty6() {
assert_decompressed_input_matches_output(include_bytes!("../../testdata/empty.compressed.06"),
include_bytes!("../../testdata/empty"),
65536,
65536);
}
#[test]
fn test_empty7() {
assert_decompressed_input_matches_output(include_bytes!("../../testdata/empty.compressed.07"),
include_bytes!("../../testdata/empty"),
65536,
65536);
}
#[test]
fn test_empty8() {
assert_decompressed_input_matches_output(include_bytes!("../../testdata/empty.compressed.08"),
include_bytes!("../../testdata/empty"),
65536,
65536);
}
#[test]
fn test_empty9() {
assert_decompressed_input_matches_output(include_bytes!("../../testdata/empty.compressed.09"),
include_bytes!("../../testdata/empty"),
65536,
65536);
}
#[test]
fn test_empty10() {
assert_decompressed_input_matches_output(include_bytes!("../../testdata/empty.compressed.10"),
include_bytes!("../../testdata/empty"),
65536,
65536);
}
#[test]
fn test_empty11() {
assert_decompressed_input_matches_output(include_bytes!("../../testdata/empty.compressed.11"),
include_bytes!("../../testdata/empty"),
65536,
65536);
}
#[test]
fn test_empty12() {
assert_decompressed_input_matches_output(include_bytes!("../../testdata/empty.compressed.12"),
include_bytes!("../../testdata/empty"),
65536,
65536);
}
#[test]
fn test_empty13() {
assert_decompressed_input_matches_output(include_bytes!("../../testdata/empty.compressed.13"),
include_bytes!("../../testdata/empty"),
65536,
65536);
}
#[test]
fn test_empty14() {
assert_decompressed_input_matches_output(include_bytes!("../../testdata/empty.compressed.14"),
include_bytes!("../../testdata/empty"),
65536,
65536);
}
#[test]
fn test_empty15() {
assert_decompressed_input_matches_output(include_bytes!("../../testdata/empty.compressed.15"),
include_bytes!("../../testdata/empty"),
65536,
65536);
}
#[test]
fn test_empty16() {
assert_decompressed_input_matches_output(include_bytes!("../../testdata/empty.compressed.16"),
include_bytes!("../../testdata/empty"),
65536,
65536);
}
#[test]
fn test_empty17() {
assert_decompressed_input_matches_output(include_bytes!("../../testdata/empty.compressed.17"),
include_bytes!("../../testdata/empty"),
65536,
65536);
}
#[test]
fn test_empty18() {
assert_decompressed_input_matches_output(include_bytes!("../../testdata/empty.compressed.18"),
include_bytes!("../../testdata/empty"),
65536,
65536);
}