diff --git a/Cargo.toml b/Cargo.toml index b51ec3c7d..85af1fdad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ doc = false libc = "0.2.5" [dev-dependencies] +rand = "0.3.14" skeptic = "0.4" [build-dependencies] diff --git a/src/decoder.rs b/src/decoder.rs index c1cacc0fd..7ca62b4a0 100644 --- a/src/decoder.rs +++ b/src/decoder.rs @@ -110,13 +110,67 @@ impl Drop for DecoderContext { #[cfg(test)] mod test { - use std::io::{Cursor, Read, Write}; + extern crate rand; + use std::io::{Cursor, Read, Write, Result, Error, ErrorKind}; + use self::rand::{Rng, StdRng}; use super::super::encoder::{Encoder, EncoderBuilder}; use super::Decoder; const BUFFER_SIZE: usize = 64 * 1024; const END_MARK: [u8; 4] = [0x9f, 0x77, 0x22, 0x71]; + struct ErrorWrapper { + r: R, + rng: Rn, + } + + impl ErrorWrapper { + fn new(rng: Rn, read: R) -> Self { + ErrorWrapper { + r: read, + rng: rng, + } + } + } + + impl Read for ErrorWrapper { + fn read(&mut self, buf: &mut [u8]) -> Result { + if self.rng.next_u32() & 0x03 == 0 { + self.r.read(buf) + } else { + Err(Error::new(ErrorKind::Other, "Opss...")) + } + } + } + + struct RetryWrapper { + r: R, + } + + impl RetryWrapper { + fn new(read: R) -> Self { + RetryWrapper { r: read } + } + } + + impl Read for RetryWrapper { + fn read(&mut self, buf: &mut [u8]) -> Result { + loop { + match self.r.read(buf) { + Ok(v) => { + return Ok(v); + } + Err(e) => { + if e.kind() == ErrorKind::Other { + continue; + } + return Err(e); + } + } + } + } + } + fn finish_encode(encoder: Encoder) -> W { let (mut buffer, result) = encoder.finish(); result.unwrap(); @@ -125,13 +179,13 @@ mod test { } fn finish_decode(decoder: Decoder) { - let (mut buffer, result) = decoder.finish(); + let (buffer, result) = decoder.finish(); result.unwrap(); let mut mark = Vec::new(); let mut data = Vec::new(); mark.write(&END_MARK).unwrap(); - buffer.read_to_end(&mut data).unwrap(); + RetryWrapper::new(buffer).read_to_end(&mut data).unwrap(); assert_eq!(mark, data); } @@ -167,13 +221,9 @@ mod test { #[test] fn test_decoder_random() { + let mut rnd = random(); + let expected = random_stream(&mut rnd, 1027 * 1023 * 7); let mut encoder = EncoderBuilder::new().level(1).build(Vec::new()).unwrap(); - let mut expected = Vec::new(); - let mut rnd: u32 = 42; - for _ in 0..1027 * 1023 * 7 { - expected.push((rnd & 0xFF) as u8); - rnd = ((1664525 as u64) * (rnd as u64) + (1013904223 as u64)) as u32; - } encoder.write(&expected).unwrap(); let encoded = finish_encode(encoder); @@ -190,4 +240,41 @@ mod test { assert_eq!(expected, actual); finish_decode(decoder); } + + #[test] + fn test_retry_read() { + let mut rnd = random(); + let expected = random_stream(&mut rnd, 1027 * 1023 * 7); + let mut encoder = EncoderBuilder::new().level(1).build(Vec::new()).unwrap(); + encoder.write(&expected).unwrap(); + let encoded = finish_encode(encoder); + + let mut decoder = Decoder::new(ErrorWrapper::new(rnd.clone(), Cursor::new(encoded))) + .unwrap(); + let mut actual = Vec::new(); + loop { + let mut buffer = [0; BUFFER_SIZE]; + match decoder.read(&mut buffer) { + Ok(size) => { + if size == 0 { + break; + } + actual.write(&buffer[0..size]).unwrap(); + } + Err(_) => {} + } + } + + assert_eq!(expected, actual); + finish_decode(decoder); + } + + fn random() -> StdRng { + let seed: &[_] = &[0xCD, 0x14, 0xD7, 0x08]; + rand::SeedableRng::from_seed(seed) + } + + fn random_stream(rng: &mut R, size: usize) -> Vec { + rand::sample(rng, 0x00..0xFF, size) + } }