1 use super::{copy_encode, decode_all, encode_all};
2 use super::{Decoder, Encoder};
3 
4 use partial_io::{PartialOp, PartialWrite};
5 
6 use std::io;
7 use std::iter;
8 
9 #[test]
test_end_of_frame()10 fn test_end_of_frame() {
11     use std::io::{Read, Write};
12 
13     let mut enc = Encoder::new(Vec::new(), 1).unwrap();
14     enc.write_all(b"foo").unwrap();
15     let mut compressed = enc.finish().unwrap();
16 
17     // Add footer/whatever to underlying storage.
18     compressed.push(0);
19 
20     // Drain zstd stream until end-of-frame.
21     let mut dec = Decoder::new(&compressed[..]).unwrap().single_frame();
22     let mut buf = Vec::new();
23     dec.read_to_end(&mut buf).unwrap();
24     assert_eq!(&buf, b"foo", "Error decoding a single frame.");
25 }
26 
27 #[test]
test_concatenated_frames()28 fn test_concatenated_frames() {
29     let mut buffer = Vec::new();
30     copy_encode(&b"foo"[..], &mut buffer, 1).unwrap();
31     copy_encode(&b"bar"[..], &mut buffer, 2).unwrap();
32     copy_encode(&b"baz"[..], &mut buffer, 3).unwrap();
33 
34     assert_eq!(
35         &decode_all(&buffer[..]).unwrap(),
36         b"foobarbaz",
37         "Error decoding concatenated frames."
38     );
39 }
40 
41 #[test]
test_flush()42 fn test_flush() {
43     use std::io::Write;
44 
45     let buf = Vec::new();
46     let mut z = Encoder::new(buf, 19).unwrap();
47 
48     z.write_all(b"hello").unwrap();
49 
50     z.flush().unwrap(); // Might corrupt stream
51     let buf = z.finish().unwrap();
52 
53     let s = decode_all(&buf[..]).unwrap();
54     assert_eq!(s, b"hello", "Error decoding after flush.");
55 }
56 
57 #[test]
test_try_finish()58 fn test_try_finish() {
59     use std::io::Write;
60     let mut z = setup_try_finish();
61 
62     z.get_mut().set_ops(iter::repeat(PartialOp::Unlimited));
63 
64     // flush() should continue to work even though write() doesn't.
65     z.flush().unwrap();
66 
67     let buf = match z.try_finish() {
68         Ok(buf) => buf.into_inner(),
69         Err((_z, e)) => panic!("try_finish failed with {:?}", e),
70     };
71 
72     // Make sure the multiple try_finish calls didn't screw up the internal
73     // buffer and continued to produce valid compressed data.
74     assert_eq!(&decode_all(&buf[..]).unwrap(), b"hello", "Error decoding");
75 }
76 
77 #[test]
78 #[should_panic]
test_write_after_try_finish()79 fn test_write_after_try_finish() {
80     use std::io::Write;
81     let mut z = setup_try_finish();
82     z.write_all(b"hello world").unwrap();
83 }
84 
setup_try_finish() -> Encoder<PartialWrite<Vec<u8>>>85 fn setup_try_finish() -> Encoder<PartialWrite<Vec<u8>>> {
86     use std::io::Write;
87 
88     let buf =
89         PartialWrite::new(Vec::new(), iter::repeat(PartialOp::Unlimited));
90     let mut z = Encoder::new(buf, 19).unwrap();
91 
92     z.write_all(b"hello").unwrap();
93 
94     z.get_mut()
95         .set_ops(iter::repeat(PartialOp::Err(io::ErrorKind::WouldBlock)));
96 
97     let (z, err) = z.try_finish().unwrap_err();
98     assert_eq!(
99         err.kind(),
100         io::ErrorKind::WouldBlock,
101         "expected WouldBlock error"
102     );
103 
104     z
105 }
106 
107 #[test]
test_failing_write()108 fn test_failing_write() {
109     use std::io::Write;
110 
111     let buf = PartialWrite::new(
112         Vec::new(),
113         iter::repeat(PartialOp::Err(io::ErrorKind::WouldBlock)),
114     );
115     let mut z = Encoder::new(buf, 1).unwrap();
116 
117     // Fill in enough data to make sure the buffer gets written out.
118     let input = vec![b'b'; 128 * 1024];
119     // This should work even though the inner writer rejects writes.
120     assert_eq!(
121         z.write(&input).unwrap(),
122         128 * 1024,
123         "did not write all input buffer"
124     );
125 
126     // The next write would fail (the buffer still has some data in it).
127     assert_eq!(
128         z.write(b"abc").unwrap_err().kind(),
129         io::ErrorKind::WouldBlock,
130         "expected WouldBlock error"
131     );
132 
133     z.get_mut().set_ops(iter::repeat(PartialOp::Unlimited));
134 
135     // This shouldn't have led to any corruption.
136     let buf = z.finish().unwrap().into_inner();
137     assert_eq!(
138         &decode_all(&buf[..]).unwrap(),
139         &input,
140         "WouldBlock errors should not corrupt stream"
141     );
142 }
143 
144 #[test]
test_invalid_frame()145 fn test_invalid_frame() {
146     use std::io::Read;
147 
148     // I really hope this data is invalid...
149     let data = &[1u8, 2u8, 3u8, 4u8, 5u8];
150     let mut dec = Decoder::new(&data[..]).unwrap();
151     assert_eq!(
152         dec.read_to_end(&mut Vec::new()).err().map(|e| e.kind()),
153         Some(io::ErrorKind::Other),
154         "did not encounter expected 'invalid frame' error"
155     );
156 }
157 
158 #[test]
test_incomplete_frame()159 fn test_incomplete_frame() {
160     use std::io::{Read, Write};
161 
162     let mut enc = Encoder::new(Vec::new(), 1).unwrap();
163     enc.write_all(b"This is a regular string").unwrap();
164     let mut compressed = enc.finish().unwrap();
165 
166     let half_size = compressed.len() - 2;
167     compressed.truncate(half_size);
168 
169     let mut dec = Decoder::new(&compressed[..]).unwrap();
170     assert_eq!(
171         dec.read_to_end(&mut Vec::new()).err().map(|e| e.kind()),
172         Some(io::ErrorKind::UnexpectedEof),
173         "did not encounter expected EOF error"
174     );
175 }
176 
177 #[test]
test_cli_compatibility()178 fn test_cli_compatibility() {
179     let input = include_bytes!("../../assets/example.txt.zst");
180 
181     let output = decode_all(&input[..]).unwrap();
182 
183     let expected = include_bytes!("../../assets/example.txt");
184 
185     assert_eq!(
186         &output[..],
187         &expected[..],
188         "error decoding cli-compressed data"
189     );
190 }
191 
192 #[cfg(feature = "legacy")]
193 #[test]
test_legacy()194 fn test_legacy() {
195     use std::fs;
196     use std::io::Read;
197 
198     // Read the content from that file
199     let expected = include_bytes!("../../assets/example.txt");
200 
201     for version in &[5, 6, 7, 8] {
202         let filename = format!("assets/example.txt.v{}.zst", version);
203         let file = fs::File::open(filename).unwrap();
204         let mut decoder = Decoder::new(file).unwrap();
205 
206         let mut buffer = Vec::new();
207         decoder.read_to_end(&mut buffer).unwrap();
208 
209         assert_eq!(
210             &expected[..],
211             &buffer[..],
212             "error decompressing legacy version {}",
213             version
214         );
215     }
216 }
217 
218 // Check that compressing+decompressing some data gives back the original
test_full_cycle(input: &[u8], level: i32)219 fn test_full_cycle(input: &[u8], level: i32) {
220     crate::test_cycle_unwrap(
221         input,
222         |data| encode_all(data, level),
223         |data| decode_all(data),
224     );
225 }
226 
227 #[test]
test_empty()228 fn test_empty() {
229     // Test compressing empty data
230     for level in 1..19 {
231         test_full_cycle(b"", level);
232     }
233 }
234 
235 #[test]
test_ll_source()236 fn test_ll_source() {
237     // Where could I find some long text?...
238     let data = include_bytes!("../../zstd-safe/zstd-sys/src/bindings.rs");
239     // Test a few compression levels.
240     // TODO: check them all?
241     for level in 1..5 {
242         // Test compressing actual data
243         test_full_cycle(data, level);
244     }
245 }
246