]>
Commit | Line | Data |
---|---|---|
1b1a35ee | 1 | use crate::io::prelude::*; |
f2b60f7d FG |
2 | use crate::io::{ |
3 | self, BorrowedBuf, BufReader, BufWriter, ErrorKind, IoSlice, LineWriter, SeekFrom, | |
4 | }; | |
a2a8927a | 5 | use crate::mem::MaybeUninit; |
1b1a35ee XL |
6 | use crate::panic; |
7 | use crate::sync::atomic::{AtomicUsize, Ordering}; | |
8 | use crate::thread; | |
9 | ||
10 | /// A dummy reader intended at testing short-reads propagation. | |
11 | pub struct ShortReader { | |
12 | lengths: Vec<usize>, | |
13 | } | |
14 | ||
15 | // FIXME: rustfmt and tidy disagree about the correct formatting of this | |
16 | // function. This leads to issues for users with editors configured to | |
17 | // rustfmt-on-save. | |
18 | impl Read for ShortReader { | |
19 | fn read(&mut self, _: &mut [u8]) -> io::Result<usize> { | |
20 | if self.lengths.is_empty() { Ok(0) } else { Ok(self.lengths.remove(0)) } | |
21 | } | |
22 | } | |
23 | ||
24 | #[test] | |
25 | fn test_buffered_reader() { | |
26 | let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4]; | |
27 | let mut reader = BufReader::with_capacity(2, inner); | |
28 | ||
29 | let mut buf = [0, 0, 0]; | |
30 | let nread = reader.read(&mut buf); | |
31 | assert_eq!(nread.unwrap(), 3); | |
32 | assert_eq!(buf, [5, 6, 7]); | |
33 | assert_eq!(reader.buffer(), []); | |
34 | ||
35 | let mut buf = [0, 0]; | |
36 | let nread = reader.read(&mut buf); | |
37 | assert_eq!(nread.unwrap(), 2); | |
38 | assert_eq!(buf, [0, 1]); | |
39 | assert_eq!(reader.buffer(), []); | |
40 | ||
41 | let mut buf = [0]; | |
42 | let nread = reader.read(&mut buf); | |
43 | assert_eq!(nread.unwrap(), 1); | |
44 | assert_eq!(buf, [2]); | |
45 | assert_eq!(reader.buffer(), [3]); | |
46 | ||
47 | let mut buf = [0, 0, 0]; | |
48 | let nread = reader.read(&mut buf); | |
49 | assert_eq!(nread.unwrap(), 1); | |
50 | assert_eq!(buf, [3, 0, 0]); | |
51 | assert_eq!(reader.buffer(), []); | |
52 | ||
53 | let nread = reader.read(&mut buf); | |
54 | assert_eq!(nread.unwrap(), 1); | |
55 | assert_eq!(buf, [4, 0, 0]); | |
56 | assert_eq!(reader.buffer(), []); | |
57 | ||
58 | assert_eq!(reader.read(&mut buf).unwrap(), 0); | |
59 | } | |
60 | ||
a2a8927a XL |
61 | #[test] |
62 | fn test_buffered_reader_read_buf() { | |
63 | let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4]; | |
64 | let mut reader = BufReader::with_capacity(2, inner); | |
65 | ||
f2b60f7d FG |
66 | let buf: &mut [_] = &mut [MaybeUninit::uninit(); 3]; |
67 | let mut buf: BorrowedBuf<'_> = buf.into(); | |
a2a8927a | 68 | |
f2b60f7d | 69 | reader.read_buf(buf.unfilled()).unwrap(); |
a2a8927a XL |
70 | |
71 | assert_eq!(buf.filled(), [5, 6, 7]); | |
72 | assert_eq!(reader.buffer(), []); | |
73 | ||
f2b60f7d FG |
74 | let buf: &mut [_] = &mut [MaybeUninit::uninit(); 2]; |
75 | let mut buf: BorrowedBuf<'_> = buf.into(); | |
a2a8927a | 76 | |
f2b60f7d | 77 | reader.read_buf(buf.unfilled()).unwrap(); |
a2a8927a XL |
78 | |
79 | assert_eq!(buf.filled(), [0, 1]); | |
80 | assert_eq!(reader.buffer(), []); | |
81 | ||
f2b60f7d FG |
82 | let buf: &mut [_] = &mut [MaybeUninit::uninit(); 1]; |
83 | let mut buf: BorrowedBuf<'_> = buf.into(); | |
a2a8927a | 84 | |
f2b60f7d | 85 | reader.read_buf(buf.unfilled()).unwrap(); |
a2a8927a XL |
86 | |
87 | assert_eq!(buf.filled(), [2]); | |
88 | assert_eq!(reader.buffer(), [3]); | |
89 | ||
f2b60f7d FG |
90 | let buf: &mut [_] = &mut [MaybeUninit::uninit(); 3]; |
91 | let mut buf: BorrowedBuf<'_> = buf.into(); | |
a2a8927a | 92 | |
f2b60f7d | 93 | reader.read_buf(buf.unfilled()).unwrap(); |
a2a8927a XL |
94 | |
95 | assert_eq!(buf.filled(), [3]); | |
96 | assert_eq!(reader.buffer(), []); | |
97 | ||
f2b60f7d | 98 | reader.read_buf(buf.unfilled()).unwrap(); |
a2a8927a XL |
99 | |
100 | assert_eq!(buf.filled(), [3, 4]); | |
101 | assert_eq!(reader.buffer(), []); | |
102 | ||
103 | buf.clear(); | |
104 | ||
f2b60f7d | 105 | reader.read_buf(buf.unfilled()).unwrap(); |
a2a8927a | 106 | |
f2b60f7d | 107 | assert!(buf.filled().is_empty()); |
a2a8927a XL |
108 | } |
109 | ||
1b1a35ee XL |
110 | #[test] |
111 | fn test_buffered_reader_seek() { | |
112 | let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4]; | |
113 | let mut reader = BufReader::with_capacity(2, io::Cursor::new(inner)); | |
114 | ||
115 | assert_eq!(reader.seek(SeekFrom::Start(3)).ok(), Some(3)); | |
116 | assert_eq!(reader.fill_buf().ok(), Some(&[0, 1][..])); | |
e8be2606 | 117 | assert_eq!(reader.stream_position().ok(), Some(3)); |
1b1a35ee XL |
118 | assert_eq!(reader.fill_buf().ok(), Some(&[0, 1][..])); |
119 | assert_eq!(reader.seek(SeekFrom::Current(1)).ok(), Some(4)); | |
120 | assert_eq!(reader.fill_buf().ok(), Some(&[1, 2][..])); | |
121 | reader.consume(1); | |
122 | assert_eq!(reader.seek(SeekFrom::Current(-2)).ok(), Some(3)); | |
123 | } | |
124 | ||
125 | #[test] | |
126 | fn test_buffered_reader_seek_relative() { | |
127 | let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4]; | |
128 | let mut reader = BufReader::with_capacity(2, io::Cursor::new(inner)); | |
129 | ||
130 | assert!(reader.seek_relative(3).is_ok()); | |
131 | assert_eq!(reader.fill_buf().ok(), Some(&[0, 1][..])); | |
132 | assert!(reader.seek_relative(0).is_ok()); | |
133 | assert_eq!(reader.fill_buf().ok(), Some(&[0, 1][..])); | |
134 | assert!(reader.seek_relative(1).is_ok()); | |
135 | assert_eq!(reader.fill_buf().ok(), Some(&[1][..])); | |
136 | assert!(reader.seek_relative(-1).is_ok()); | |
137 | assert_eq!(reader.fill_buf().ok(), Some(&[0, 1][..])); | |
138 | assert!(reader.seek_relative(2).is_ok()); | |
139 | assert_eq!(reader.fill_buf().ok(), Some(&[2, 3][..])); | |
140 | } | |
141 | ||
142 | #[test] | |
143 | fn test_buffered_reader_stream_position() { | |
144 | let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4]; | |
145 | let mut reader = BufReader::with_capacity(2, io::Cursor::new(inner)); | |
146 | ||
147 | assert_eq!(reader.stream_position().ok(), Some(0)); | |
148 | assert_eq!(reader.seek(SeekFrom::Start(3)).ok(), Some(3)); | |
149 | assert_eq!(reader.stream_position().ok(), Some(3)); | |
150 | // relative seeking within the buffer and reading position should keep the buffer | |
151 | assert_eq!(reader.fill_buf().ok(), Some(&[0, 1][..])); | |
152 | assert!(reader.seek_relative(0).is_ok()); | |
153 | assert_eq!(reader.stream_position().ok(), Some(3)); | |
154 | assert_eq!(reader.buffer(), &[0, 1][..]); | |
155 | assert!(reader.seek_relative(1).is_ok()); | |
156 | assert_eq!(reader.stream_position().ok(), Some(4)); | |
157 | assert_eq!(reader.buffer(), &[1][..]); | |
158 | assert!(reader.seek_relative(-1).is_ok()); | |
159 | assert_eq!(reader.stream_position().ok(), Some(3)); | |
160 | assert_eq!(reader.buffer(), &[0, 1][..]); | |
161 | // relative seeking outside the buffer will discard it | |
162 | assert!(reader.seek_relative(2).is_ok()); | |
163 | assert_eq!(reader.stream_position().ok(), Some(5)); | |
164 | assert_eq!(reader.buffer(), &[][..]); | |
165 | } | |
166 | ||
167 | #[test] | |
168 | fn test_buffered_reader_stream_position_panic() { | |
169 | let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4]; | |
170 | let mut reader = BufReader::with_capacity(4, io::Cursor::new(inner)); | |
171 | ||
172 | // cause internal buffer to be filled but read only partially | |
173 | let mut buffer = [0, 0]; | |
174 | assert!(reader.read_exact(&mut buffer).is_ok()); | |
175 | // rewinding the internal reader will cause buffer to loose sync | |
176 | let inner = reader.get_mut(); | |
177 | assert!(inner.seek(SeekFrom::Start(0)).is_ok()); | |
178 | // overflow when subtracting the remaining buffer size from current position | |
179 | let result = panic::catch_unwind(panic::AssertUnwindSafe(|| reader.stream_position().ok())); | |
180 | assert!(result.is_err()); | |
181 | } | |
182 | ||
183 | #[test] | |
184 | fn test_buffered_reader_invalidated_after_read() { | |
185 | let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4]; | |
186 | let mut reader = BufReader::with_capacity(3, io::Cursor::new(inner)); | |
187 | ||
188 | assert_eq!(reader.fill_buf().ok(), Some(&[5, 6, 7][..])); | |
189 | reader.consume(3); | |
190 | ||
191 | let mut buffer = [0, 0, 0, 0, 0]; | |
192 | assert_eq!(reader.read(&mut buffer).ok(), Some(5)); | |
193 | assert_eq!(buffer, [0, 1, 2, 3, 4]); | |
194 | ||
195 | assert!(reader.seek_relative(-2).is_ok()); | |
196 | let mut buffer = [0, 0]; | |
197 | assert_eq!(reader.read(&mut buffer).ok(), Some(2)); | |
198 | assert_eq!(buffer, [3, 4]); | |
199 | } | |
200 | ||
201 | #[test] | |
202 | fn test_buffered_reader_invalidated_after_seek() { | |
203 | let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4]; | |
204 | let mut reader = BufReader::with_capacity(3, io::Cursor::new(inner)); | |
205 | ||
206 | assert_eq!(reader.fill_buf().ok(), Some(&[5, 6, 7][..])); | |
207 | reader.consume(3); | |
208 | ||
209 | assert!(reader.seek(SeekFrom::Current(5)).is_ok()); | |
210 | ||
211 | assert!(reader.seek_relative(-2).is_ok()); | |
212 | let mut buffer = [0, 0]; | |
213 | assert_eq!(reader.read(&mut buffer).ok(), Some(2)); | |
214 | assert_eq!(buffer, [3, 4]); | |
215 | } | |
216 | ||
217 | #[test] | |
218 | fn test_buffered_reader_seek_underflow() { | |
219 | // gimmick reader that yields its position modulo 256 for each byte | |
220 | struct PositionReader { | |
221 | pos: u64, | |
222 | } | |
223 | impl Read for PositionReader { | |
224 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | |
225 | let len = buf.len(); | |
226 | for x in buf { | |
227 | *x = self.pos as u8; | |
228 | self.pos = self.pos.wrapping_add(1); | |
229 | } | |
230 | Ok(len) | |
231 | } | |
232 | } | |
e8be2606 FG |
233 | // note: this implementation of `Seek` is "broken" due to position |
234 | // wrapping, so calling `reader.seek(Current(0))` is semantically different | |
235 | // than `reader.stream_position()` | |
1b1a35ee XL |
236 | impl Seek for PositionReader { |
237 | fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> { | |
238 | match pos { | |
239 | SeekFrom::Start(n) => { | |
240 | self.pos = n; | |
241 | } | |
242 | SeekFrom::Current(n) => { | |
243 | self.pos = self.pos.wrapping_add(n as u64); | |
244 | } | |
245 | SeekFrom::End(n) => { | |
246 | self.pos = u64::MAX.wrapping_add(n as u64); | |
247 | } | |
248 | } | |
249 | Ok(self.pos) | |
250 | } | |
251 | } | |
252 | ||
253 | let mut reader = BufReader::with_capacity(5, PositionReader { pos: 0 }); | |
254 | assert_eq!(reader.fill_buf().ok(), Some(&[0, 1, 2, 3, 4][..])); | |
255 | assert_eq!(reader.seek(SeekFrom::End(-5)).ok(), Some(u64::MAX - 5)); | |
256 | assert_eq!(reader.fill_buf().ok().map(|s| s.len()), Some(5)); | |
257 | // the following seek will require two underlying seeks | |
258 | let expected = 9223372036854775802; | |
259 | assert_eq!(reader.seek(SeekFrom::Current(i64::MIN)).ok(), Some(expected)); | |
260 | assert_eq!(reader.fill_buf().ok().map(|s| s.len()), Some(5)); | |
261 | // seeking to 0 should empty the buffer. | |
262 | assert_eq!(reader.seek(SeekFrom::Current(0)).ok(), Some(expected)); | |
263 | assert_eq!(reader.get_ref().pos, expected); | |
264 | } | |
265 | ||
266 | #[test] | |
267 | fn test_buffered_reader_seek_underflow_discard_buffer_between_seeks() { | |
268 | // gimmick reader that returns Err after first seek | |
269 | struct ErrAfterFirstSeekReader { | |
270 | first_seek: bool, | |
271 | } | |
272 | impl Read for ErrAfterFirstSeekReader { | |
273 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | |
274 | for x in &mut *buf { | |
275 | *x = 0; | |
276 | } | |
277 | Ok(buf.len()) | |
278 | } | |
279 | } | |
280 | impl Seek for ErrAfterFirstSeekReader { | |
281 | fn seek(&mut self, _: SeekFrom) -> io::Result<u64> { | |
282 | if self.first_seek { | |
283 | self.first_seek = false; | |
284 | Ok(0) | |
285 | } else { | |
286 | Err(io::Error::new(io::ErrorKind::Other, "oh no!")) | |
287 | } | |
288 | } | |
289 | } | |
290 | ||
291 | let mut reader = BufReader::with_capacity(5, ErrAfterFirstSeekReader { first_seek: true }); | |
292 | assert_eq!(reader.fill_buf().ok(), Some(&[0, 0, 0, 0, 0][..])); | |
293 | ||
9c376795 FG |
294 | // The following seek will require two underlying seeks. The first will |
295 | // succeed but the second will fail. This should still invalidate the | |
1b1a35ee XL |
296 | // buffer. |
297 | assert!(reader.seek(SeekFrom::Current(i64::MIN)).is_err()); | |
298 | assert_eq!(reader.buffer().len(), 0); | |
299 | } | |
300 | ||
c295e0f8 XL |
301 | #[test] |
302 | fn test_buffered_reader_read_to_end_consumes_buffer() { | |
303 | let data: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7]; | |
304 | let mut reader = BufReader::with_capacity(3, data); | |
305 | let mut buf = Vec::new(); | |
306 | assert_eq!(reader.fill_buf().ok(), Some(&[0, 1, 2][..])); | |
307 | assert_eq!(reader.read_to_end(&mut buf).ok(), Some(8)); | |
308 | assert_eq!(&buf, &[0, 1, 2, 3, 4, 5, 6, 7]); | |
309 | assert!(reader.buffer().is_empty()); | |
310 | } | |
311 | ||
312 | #[test] | |
313 | fn test_buffered_reader_read_to_string_consumes_buffer() { | |
314 | let data: &[u8] = "deadbeef".as_bytes(); | |
315 | let mut reader = BufReader::with_capacity(3, data); | |
316 | let mut buf = String::new(); | |
317 | assert_eq!(reader.fill_buf().ok(), Some("dea".as_bytes())); | |
318 | assert_eq!(reader.read_to_string(&mut buf).ok(), Some(8)); | |
319 | assert_eq!(&buf, "deadbeef"); | |
320 | assert!(reader.buffer().is_empty()); | |
321 | } | |
322 | ||
1b1a35ee XL |
323 | #[test] |
324 | fn test_buffered_writer() { | |
325 | let inner = Vec::new(); | |
326 | let mut writer = BufWriter::with_capacity(2, inner); | |
327 | ||
328 | writer.write(&[0, 1]).unwrap(); | |
329 | assert_eq!(writer.buffer(), []); | |
330 | assert_eq!(*writer.get_ref(), [0, 1]); | |
331 | ||
332 | writer.write(&[2]).unwrap(); | |
333 | assert_eq!(writer.buffer(), [2]); | |
334 | assert_eq!(*writer.get_ref(), [0, 1]); | |
335 | ||
336 | writer.write(&[3]).unwrap(); | |
337 | assert_eq!(writer.buffer(), [2, 3]); | |
338 | assert_eq!(*writer.get_ref(), [0, 1]); | |
339 | ||
340 | writer.flush().unwrap(); | |
341 | assert_eq!(writer.buffer(), []); | |
342 | assert_eq!(*writer.get_ref(), [0, 1, 2, 3]); | |
343 | ||
344 | writer.write(&[4]).unwrap(); | |
345 | writer.write(&[5]).unwrap(); | |
346 | assert_eq!(writer.buffer(), [4, 5]); | |
347 | assert_eq!(*writer.get_ref(), [0, 1, 2, 3]); | |
348 | ||
349 | writer.write(&[6]).unwrap(); | |
350 | assert_eq!(writer.buffer(), [6]); | |
351 | assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5]); | |
352 | ||
353 | writer.write(&[7, 8]).unwrap(); | |
354 | assert_eq!(writer.buffer(), []); | |
355 | assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8]); | |
356 | ||
357 | writer.write(&[9, 10, 11]).unwrap(); | |
358 | assert_eq!(writer.buffer(), []); | |
359 | assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]); | |
360 | ||
361 | writer.flush().unwrap(); | |
362 | assert_eq!(writer.buffer(), []); | |
363 | assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]); | |
364 | } | |
365 | ||
366 | #[test] | |
367 | fn test_buffered_writer_inner_flushes() { | |
368 | let mut w = BufWriter::with_capacity(3, Vec::new()); | |
369 | w.write(&[0, 1]).unwrap(); | |
370 | assert_eq!(*w.get_ref(), []); | |
371 | let w = w.into_inner().unwrap(); | |
372 | assert_eq!(w, [0, 1]); | |
373 | } | |
374 | ||
375 | #[test] | |
376 | fn test_buffered_writer_seek() { | |
377 | let mut w = BufWriter::with_capacity(3, io::Cursor::new(Vec::new())); | |
378 | w.write_all(&[0, 1, 2, 3, 4, 5]).unwrap(); | |
379 | w.write_all(&[6, 7]).unwrap(); | |
e8be2606 | 380 | assert_eq!(w.stream_position().ok(), Some(8)); |
1b1a35ee XL |
381 | assert_eq!(&w.get_ref().get_ref()[..], &[0, 1, 2, 3, 4, 5, 6, 7][..]); |
382 | assert_eq!(w.seek(SeekFrom::Start(2)).ok(), Some(2)); | |
383 | w.write_all(&[8, 9]).unwrap(); | |
384 | assert_eq!(&w.into_inner().unwrap().into_inner()[..], &[0, 1, 8, 9, 4, 5, 6, 7]); | |
385 | } | |
386 | ||
387 | #[test] | |
388 | fn test_read_until() { | |
389 | let inner: &[u8] = &[0, 1, 2, 1, 0]; | |
390 | let mut reader = BufReader::with_capacity(2, inner); | |
391 | let mut v = Vec::new(); | |
392 | reader.read_until(0, &mut v).unwrap(); | |
393 | assert_eq!(v, [0]); | |
394 | v.truncate(0); | |
395 | reader.read_until(2, &mut v).unwrap(); | |
396 | assert_eq!(v, [1, 2]); | |
397 | v.truncate(0); | |
398 | reader.read_until(1, &mut v).unwrap(); | |
399 | assert_eq!(v, [1]); | |
400 | v.truncate(0); | |
401 | reader.read_until(8, &mut v).unwrap(); | |
402 | assert_eq!(v, [0]); | |
403 | v.truncate(0); | |
404 | reader.read_until(9, &mut v).unwrap(); | |
405 | assert_eq!(v, []); | |
406 | } | |
407 | ||
408 | #[test] | |
409 | fn test_line_buffer() { | |
410 | let mut writer = LineWriter::new(Vec::new()); | |
411 | writer.write(&[0]).unwrap(); | |
412 | assert_eq!(*writer.get_ref(), []); | |
413 | writer.write(&[1]).unwrap(); | |
414 | assert_eq!(*writer.get_ref(), []); | |
415 | writer.flush().unwrap(); | |
416 | assert_eq!(*writer.get_ref(), [0, 1]); | |
417 | writer.write(&[0, b'\n', 1, b'\n', 2]).unwrap(); | |
418 | assert_eq!(*writer.get_ref(), [0, 1, 0, b'\n', 1, b'\n']); | |
419 | writer.flush().unwrap(); | |
420 | assert_eq!(*writer.get_ref(), [0, 1, 0, b'\n', 1, b'\n', 2]); | |
421 | writer.write(&[3, b'\n']).unwrap(); | |
422 | assert_eq!(*writer.get_ref(), [0, 1, 0, b'\n', 1, b'\n', 2, 3, b'\n']); | |
423 | } | |
424 | ||
425 | #[test] | |
426 | fn test_read_line() { | |
427 | let in_buf: &[u8] = b"a\nb\nc"; | |
428 | let mut reader = BufReader::with_capacity(2, in_buf); | |
429 | let mut s = String::new(); | |
430 | reader.read_line(&mut s).unwrap(); | |
431 | assert_eq!(s, "a\n"); | |
432 | s.truncate(0); | |
433 | reader.read_line(&mut s).unwrap(); | |
434 | assert_eq!(s, "b\n"); | |
435 | s.truncate(0); | |
436 | reader.read_line(&mut s).unwrap(); | |
437 | assert_eq!(s, "c"); | |
438 | s.truncate(0); | |
439 | reader.read_line(&mut s).unwrap(); | |
440 | assert_eq!(s, ""); | |
441 | } | |
442 | ||
443 | #[test] | |
444 | fn test_lines() { | |
445 | let in_buf: &[u8] = b"a\nb\nc"; | |
446 | let reader = BufReader::with_capacity(2, in_buf); | |
447 | let mut it = reader.lines(); | |
448 | assert_eq!(it.next().unwrap().unwrap(), "a".to_string()); | |
449 | assert_eq!(it.next().unwrap().unwrap(), "b".to_string()); | |
450 | assert_eq!(it.next().unwrap().unwrap(), "c".to_string()); | |
451 | assert!(it.next().is_none()); | |
452 | } | |
453 | ||
454 | #[test] | |
455 | fn test_short_reads() { | |
456 | let inner = ShortReader { lengths: vec![0, 1, 2, 0, 1, 0] }; | |
457 | let mut reader = BufReader::new(inner); | |
458 | let mut buf = [0, 0]; | |
459 | assert_eq!(reader.read(&mut buf).unwrap(), 0); | |
460 | assert_eq!(reader.read(&mut buf).unwrap(), 1); | |
461 | assert_eq!(reader.read(&mut buf).unwrap(), 2); | |
462 | assert_eq!(reader.read(&mut buf).unwrap(), 0); | |
463 | assert_eq!(reader.read(&mut buf).unwrap(), 1); | |
464 | assert_eq!(reader.read(&mut buf).unwrap(), 0); | |
465 | assert_eq!(reader.read(&mut buf).unwrap(), 0); | |
466 | } | |
467 | ||
468 | #[test] | |
469 | #[should_panic] | |
470 | fn dont_panic_in_drop_on_panicked_flush() { | |
471 | struct FailFlushWriter; | |
472 | ||
473 | impl Write for FailFlushWriter { | |
474 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { | |
475 | Ok(buf.len()) | |
476 | } | |
477 | fn flush(&mut self) -> io::Result<()> { | |
478 | Err(io::Error::last_os_error()) | |
479 | } | |
480 | } | |
481 | ||
482 | let writer = FailFlushWriter; | |
483 | let _writer = BufWriter::new(writer); | |
484 | ||
485 | // If writer panics *again* due to the flush error then the process will | |
486 | // abort. | |
487 | panic!(); | |
488 | } | |
489 | ||
490 | #[test] | |
491 | #[cfg_attr(target_os = "emscripten", ignore)] | |
492 | fn panic_in_write_doesnt_flush_in_drop() { | |
493 | static WRITES: AtomicUsize = AtomicUsize::new(0); | |
494 | ||
495 | struct PanicWriter; | |
496 | ||
497 | impl Write for PanicWriter { | |
498 | fn write(&mut self, _: &[u8]) -> io::Result<usize> { | |
499 | WRITES.fetch_add(1, Ordering::SeqCst); | |
500 | panic!(); | |
501 | } | |
502 | fn flush(&mut self) -> io::Result<()> { | |
503 | Ok(()) | |
504 | } | |
505 | } | |
506 | ||
507 | thread::spawn(|| { | |
508 | let mut writer = BufWriter::new(PanicWriter); | |
509 | let _ = writer.write(b"hello world"); | |
510 | let _ = writer.flush(); | |
511 | }) | |
512 | .join() | |
513 | .unwrap_err(); | |
514 | ||
515 | assert_eq!(WRITES.load(Ordering::SeqCst), 1); | |
516 | } | |
517 | ||
518 | #[bench] | |
519 | fn bench_buffered_reader(b: &mut test::Bencher) { | |
520 | b.iter(|| BufReader::new(io::empty())); | |
521 | } | |
522 | ||
5869c6ff XL |
523 | #[bench] |
524 | fn bench_buffered_reader_small_reads(b: &mut test::Bencher) { | |
525 | let data = (0..u8::MAX).cycle().take(1024 * 4).collect::<Vec<_>>(); | |
526 | b.iter(|| { | |
527 | let mut reader = BufReader::new(&data[..]); | |
528 | let mut buf = [0u8; 4]; | |
529 | for _ in 0..1024 { | |
530 | reader.read_exact(&mut buf).unwrap(); | |
064997fb | 531 | core::hint::black_box(&buf); |
5869c6ff XL |
532 | } |
533 | }); | |
534 | } | |
535 | ||
1b1a35ee XL |
536 | #[bench] |
537 | fn bench_buffered_writer(b: &mut test::Bencher) { | |
538 | b.iter(|| BufWriter::new(io::sink())); | |
539 | } | |
540 | ||
541 | /// A simple `Write` target, designed to be wrapped by `LineWriter` / | |
542 | /// `BufWriter` / etc, that can have its `write` & `flush` behavior | |
543 | /// configured | |
544 | #[derive(Default, Clone)] | |
545 | struct ProgrammableSink { | |
546 | // Writes append to this slice | |
547 | pub buffer: Vec<u8>, | |
548 | ||
1b1a35ee XL |
549 | // If true, writes will always be an error |
550 | pub always_write_error: bool, | |
551 | ||
552 | // If true, flushes will always be an error | |
553 | pub always_flush_error: bool, | |
554 | ||
555 | // If set, only up to this number of bytes will be written in a single | |
556 | // call to `write` | |
557 | pub accept_prefix: Option<usize>, | |
558 | ||
559 | // If set, counts down with each write, and writes return an error | |
560 | // when it hits 0 | |
561 | pub max_writes: Option<usize>, | |
562 | ||
563 | // If set, attempting to write when max_writes == Some(0) will be an | |
564 | // error; otherwise, it will return Ok(0). | |
565 | pub error_after_max_writes: bool, | |
566 | } | |
567 | ||
568 | impl Write for ProgrammableSink { | |
569 | fn write(&mut self, data: &[u8]) -> io::Result<usize> { | |
570 | if self.always_write_error { | |
571 | return Err(io::Error::new(io::ErrorKind::Other, "test - always_write_error")); | |
572 | } | |
573 | ||
574 | match self.max_writes { | |
575 | Some(0) if self.error_after_max_writes => { | |
576 | return Err(io::Error::new(io::ErrorKind::Other, "test - max_writes")); | |
577 | } | |
578 | Some(0) => return Ok(0), | |
579 | Some(ref mut count) => *count -= 1, | |
580 | None => {} | |
581 | } | |
582 | ||
583 | let len = match self.accept_prefix { | |
584 | None => data.len(), | |
585 | Some(prefix) => data.len().min(prefix), | |
586 | }; | |
587 | ||
588 | let data = &data[..len]; | |
589 | self.buffer.extend_from_slice(data); | |
590 | ||
591 | Ok(len) | |
592 | } | |
593 | ||
594 | fn flush(&mut self) -> io::Result<()> { | |
595 | if self.always_flush_error { | |
596 | Err(io::Error::new(io::ErrorKind::Other, "test - always_flush_error")) | |
597 | } else { | |
1b1a35ee XL |
598 | Ok(()) |
599 | } | |
600 | } | |
601 | } | |
602 | ||
603 | /// Previously the `LineWriter` could successfully write some bytes but | |
604 | /// then fail to report that it has done so. Additionally, an erroneous | |
605 | /// flush after a successful write was permanently ignored. | |
606 | /// | |
607 | /// Test that a line writer correctly reports the number of written bytes, | |
608 | /// and that it attempts to flush buffered lines from previous writes | |
609 | /// before processing new data | |
610 | /// | |
611 | /// Regression test for #37807 | |
612 | #[test] | |
613 | fn erroneous_flush_retried() { | |
614 | let writer = ProgrammableSink { | |
615 | // Only write up to 4 bytes at a time | |
616 | accept_prefix: Some(4), | |
617 | ||
618 | // Accept the first two writes, then error the others | |
619 | max_writes: Some(2), | |
620 | error_after_max_writes: true, | |
621 | ||
622 | ..Default::default() | |
623 | }; | |
624 | ||
625 | // This should write the first 4 bytes. The rest will be buffered, out | |
626 | // to the last newline. | |
627 | let mut writer = LineWriter::new(writer); | |
628 | assert_eq!(writer.write(b"a\nb\nc\nd\ne").unwrap(), 8); | |
629 | ||
630 | // This write should attempt to flush "c\nd\n", then buffer "e". No | |
631 | // errors should happen here because no further writes should be | |
632 | // attempted against `writer`. | |
633 | assert_eq!(writer.write(b"e").unwrap(), 1); | |
634 | assert_eq!(&writer.get_ref().buffer, b"a\nb\nc\nd\n"); | |
635 | } | |
636 | ||
637 | #[test] | |
638 | fn line_vectored() { | |
639 | let mut a = LineWriter::new(Vec::new()); | |
640 | assert_eq!( | |
641 | a.write_vectored(&[ | |
642 | IoSlice::new(&[]), | |
643 | IoSlice::new(b"\n"), | |
644 | IoSlice::new(&[]), | |
645 | IoSlice::new(b"a"), | |
646 | ]) | |
647 | .unwrap(), | |
648 | 2, | |
649 | ); | |
650 | assert_eq!(a.get_ref(), b"\n"); | |
651 | ||
652 | assert_eq!( | |
653 | a.write_vectored(&[ | |
654 | IoSlice::new(&[]), | |
655 | IoSlice::new(b"b"), | |
656 | IoSlice::new(&[]), | |
657 | IoSlice::new(b"a"), | |
658 | IoSlice::new(&[]), | |
659 | IoSlice::new(b"c"), | |
660 | ]) | |
661 | .unwrap(), | |
662 | 3, | |
663 | ); | |
664 | assert_eq!(a.get_ref(), b"\n"); | |
665 | a.flush().unwrap(); | |
666 | assert_eq!(a.get_ref(), b"\nabac"); | |
667 | assert_eq!(a.write_vectored(&[]).unwrap(), 0); | |
668 | assert_eq!( | |
669 | a.write_vectored(&[ | |
670 | IoSlice::new(&[]), | |
671 | IoSlice::new(&[]), | |
672 | IoSlice::new(&[]), | |
673 | IoSlice::new(&[]), | |
674 | ]) | |
675 | .unwrap(), | |
676 | 0, | |
677 | ); | |
678 | assert_eq!(a.write_vectored(&[IoSlice::new(b"a\nb"),]).unwrap(), 3); | |
679 | assert_eq!(a.get_ref(), b"\nabaca\nb"); | |
680 | } | |
681 | ||
682 | #[test] | |
683 | fn line_vectored_partial_and_errors() { | |
684 | use crate::collections::VecDeque; | |
685 | ||
686 | enum Call { | |
687 | Write { inputs: Vec<&'static [u8]>, output: io::Result<usize> }, | |
688 | Flush { output: io::Result<()> }, | |
689 | } | |
690 | ||
691 | #[derive(Default)] | |
692 | struct Writer { | |
693 | calls: VecDeque<Call>, | |
694 | } | |
695 | ||
696 | impl Write for Writer { | |
697 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { | |
698 | self.write_vectored(&[IoSlice::new(buf)]) | |
699 | } | |
700 | ||
701 | fn write_vectored(&mut self, buf: &[IoSlice<'_>]) -> io::Result<usize> { | |
702 | match self.calls.pop_front().expect("unexpected call to write") { | |
703 | Call::Write { inputs, output } => { | |
704 | assert_eq!(inputs, buf.iter().map(|b| &**b).collect::<Vec<_>>()); | |
705 | output | |
706 | } | |
707 | Call::Flush { .. } => panic!("unexpected call to write; expected a flush"), | |
708 | } | |
709 | } | |
710 | ||
711 | fn is_write_vectored(&self) -> bool { | |
712 | true | |
713 | } | |
714 | ||
715 | fn flush(&mut self) -> io::Result<()> { | |
716 | match self.calls.pop_front().expect("Unexpected call to flush") { | |
717 | Call::Flush { output } => output, | |
718 | Call::Write { .. } => panic!("unexpected call to flush; expected a write"), | |
719 | } | |
720 | } | |
721 | } | |
722 | ||
723 | impl Drop for Writer { | |
724 | fn drop(&mut self) { | |
725 | if !thread::panicking() { | |
726 | assert_eq!(self.calls.len(), 0); | |
727 | } | |
728 | } | |
729 | } | |
730 | ||
731 | // partial writes keep going | |
732 | let mut a = LineWriter::new(Writer::default()); | |
733 | a.write_vectored(&[IoSlice::new(&[]), IoSlice::new(b"abc")]).unwrap(); | |
734 | ||
735 | a.get_mut().calls.push_back(Call::Write { inputs: vec![b"abc"], output: Ok(1) }); | |
736 | a.get_mut().calls.push_back(Call::Write { inputs: vec![b"bc"], output: Ok(2) }); | |
737 | a.get_mut().calls.push_back(Call::Write { inputs: vec![b"x", b"\n"], output: Ok(2) }); | |
738 | ||
739 | a.write_vectored(&[IoSlice::new(b"x"), IoSlice::new(b"\n")]).unwrap(); | |
740 | ||
741 | a.get_mut().calls.push_back(Call::Flush { output: Ok(()) }); | |
742 | a.flush().unwrap(); | |
743 | ||
744 | // erroneous writes stop and don't write more | |
745 | a.get_mut().calls.push_back(Call::Write { inputs: vec![b"x", b"\na"], output: Err(err()) }); | |
746 | a.get_mut().calls.push_back(Call::Flush { output: Ok(()) }); | |
747 | assert!(a.write_vectored(&[IoSlice::new(b"x"), IoSlice::new(b"\na")]).is_err()); | |
748 | a.flush().unwrap(); | |
749 | ||
750 | fn err() -> io::Error { | |
751 | io::Error::new(io::ErrorKind::Other, "x") | |
752 | } | |
753 | } | |
754 | ||
755 | /// Test that, in cases where vectored writing is not enabled, the | |
756 | /// LineWriter uses the normal `write` call, which more-correctly handles | |
757 | /// partial lines | |
758 | #[test] | |
759 | fn line_vectored_ignored() { | |
760 | let writer = ProgrammableSink::default(); | |
761 | let mut writer = LineWriter::new(writer); | |
762 | ||
763 | let content = [ | |
764 | IoSlice::new(&[]), | |
765 | IoSlice::new(b"Line 1\nLine"), | |
766 | IoSlice::new(b" 2\nLine 3\nL"), | |
767 | IoSlice::new(&[]), | |
768 | IoSlice::new(&[]), | |
769 | IoSlice::new(b"ine 4"), | |
770 | IoSlice::new(b"\nLine 5\n"), | |
771 | ]; | |
772 | ||
773 | let count = writer.write_vectored(&content).unwrap(); | |
774 | assert_eq!(count, 11); | |
775 | assert_eq!(&writer.get_ref().buffer, b"Line 1\n"); | |
776 | ||
777 | let count = writer.write_vectored(&content[2..]).unwrap(); | |
778 | assert_eq!(count, 11); | |
779 | assert_eq!(&writer.get_ref().buffer, b"Line 1\nLine 2\nLine 3\n"); | |
780 | ||
781 | let count = writer.write_vectored(&content[5..]).unwrap(); | |
782 | assert_eq!(count, 5); | |
783 | assert_eq!(&writer.get_ref().buffer, b"Line 1\nLine 2\nLine 3\n"); | |
784 | ||
785 | let count = writer.write_vectored(&content[6..]).unwrap(); | |
786 | assert_eq!(count, 8); | |
787 | assert_eq!( | |
788 | writer.get_ref().buffer.as_slice(), | |
789 | b"Line 1\nLine 2\nLine 3\nLine 4\nLine 5\n".as_ref() | |
790 | ); | |
791 | } | |
792 | ||
793 | /// Test that, given this input: | |
794 | /// | |
795 | /// Line 1\n | |
796 | /// Line 2\n | |
797 | /// Line 3\n | |
798 | /// Line 4 | |
799 | /// | |
800 | /// And given a result that only writes to midway through Line 2 | |
801 | /// | |
802 | /// That only up to the end of Line 3 is buffered | |
803 | /// | |
804 | /// This behavior is desirable because it prevents flushing partial lines | |
805 | #[test] | |
806 | fn partial_write_buffers_line() { | |
807 | let writer = ProgrammableSink { accept_prefix: Some(13), ..Default::default() }; | |
808 | let mut writer = LineWriter::new(writer); | |
809 | ||
810 | assert_eq!(writer.write(b"Line 1\nLine 2\nLine 3\nLine4").unwrap(), 21); | |
811 | assert_eq!(&writer.get_ref().buffer, b"Line 1\nLine 2"); | |
812 | ||
813 | assert_eq!(writer.write(b"Line 4").unwrap(), 6); | |
814 | assert_eq!(&writer.get_ref().buffer, b"Line 1\nLine 2\nLine 3\n"); | |
815 | } | |
816 | ||
817 | /// Test that, given this input: | |
818 | /// | |
819 | /// Line 1\n | |
820 | /// Line 2\n | |
821 | /// Line 3 | |
822 | /// | |
823 | /// And given that the full write of lines 1 and 2 was successful | |
824 | /// That data up to Line 3 is buffered | |
825 | #[test] | |
826 | fn partial_line_buffered_after_line_write() { | |
827 | let writer = ProgrammableSink::default(); | |
828 | let mut writer = LineWriter::new(writer); | |
829 | ||
830 | assert_eq!(writer.write(b"Line 1\nLine 2\nLine 3").unwrap(), 20); | |
831 | assert_eq!(&writer.get_ref().buffer, b"Line 1\nLine 2\n"); | |
832 | ||
833 | assert!(writer.flush().is_ok()); | |
834 | assert_eq!(&writer.get_ref().buffer, b"Line 1\nLine 2\nLine 3"); | |
835 | } | |
836 | ||
49aad941 FG |
837 | /// Test that for calls to LineBuffer::write where the passed bytes do not contain |
838 | /// a newline and on their own are greater in length than the internal buffer, the | |
839 | /// passed bytes are immediately written to the inner writer. | |
1b1a35ee XL |
840 | #[test] |
841 | fn long_line_flushed() { | |
842 | let writer = ProgrammableSink::default(); | |
843 | let mut writer = LineWriter::with_capacity(5, writer); | |
844 | ||
845 | assert_eq!(writer.write(b"0123456789").unwrap(), 10); | |
846 | assert_eq!(&writer.get_ref().buffer, b"0123456789"); | |
847 | } | |
848 | ||
849 | /// Test that, given a very long partial line *after* successfully | |
49aad941 FG |
850 | /// flushing a complete line, the very long partial line is buffered |
851 | /// unconditionally, and no additional writes take place. This assures | |
852 | /// the property that `write` should make at-most-one attempt to write | |
853 | /// new data. | |
1b1a35ee XL |
854 | #[test] |
855 | fn line_long_tail_not_flushed() { | |
856 | let writer = ProgrammableSink::default(); | |
857 | let mut writer = LineWriter::with_capacity(5, writer); | |
858 | ||
859 | // Assert that Line 1\n is flushed, and 01234 is buffered | |
860 | assert_eq!(writer.write(b"Line 1\n0123456789").unwrap(), 12); | |
861 | assert_eq!(&writer.get_ref().buffer, b"Line 1\n"); | |
862 | ||
863 | // Because the buffer is full, this subsequent write will flush it | |
864 | assert_eq!(writer.write(b"5").unwrap(), 1); | |
865 | assert_eq!(&writer.get_ref().buffer, b"Line 1\n01234"); | |
866 | } | |
867 | ||
868 | /// Test that, if an attempt to pre-flush buffered data returns Ok(0), | |
869 | /// this is propagated as an error. | |
870 | #[test] | |
871 | fn line_buffer_write0_error() { | |
872 | let writer = ProgrammableSink { | |
873 | // Accept one write, then return Ok(0) on subsequent ones | |
874 | max_writes: Some(1), | |
875 | ||
876 | ..Default::default() | |
877 | }; | |
878 | let mut writer = LineWriter::new(writer); | |
879 | ||
880 | // This should write "Line 1\n" and buffer "Partial" | |
881 | assert_eq!(writer.write(b"Line 1\nPartial").unwrap(), 14); | |
882 | assert_eq!(&writer.get_ref().buffer, b"Line 1\n"); | |
883 | ||
884 | // This will attempt to flush "partial", which will return Ok(0), which | |
885 | // needs to be an error, because we've already informed the client | |
886 | // that we accepted the write. | |
887 | let err = writer.write(b" Line End\n").unwrap_err(); | |
888 | assert_eq!(err.kind(), ErrorKind::WriteZero); | |
889 | assert_eq!(&writer.get_ref().buffer, b"Line 1\n"); | |
890 | } | |
891 | ||
892 | /// Test that, if a write returns Ok(0) after a successful pre-flush, this | |
893 | /// is propagated as Ok(0) | |
894 | #[test] | |
895 | fn line_buffer_write0_normal() { | |
896 | let writer = ProgrammableSink { | |
897 | // Accept two writes, then return Ok(0) on subsequent ones | |
898 | max_writes: Some(2), | |
899 | ||
900 | ..Default::default() | |
901 | }; | |
902 | let mut writer = LineWriter::new(writer); | |
903 | ||
904 | // This should write "Line 1\n" and buffer "Partial" | |
905 | assert_eq!(writer.write(b"Line 1\nPartial").unwrap(), 14); | |
906 | assert_eq!(&writer.get_ref().buffer, b"Line 1\n"); | |
907 | ||
908 | // This will flush partial, which will succeed, but then return Ok(0) | |
909 | // when flushing " Line End\n" | |
910 | assert_eq!(writer.write(b" Line End\n").unwrap(), 0); | |
911 | assert_eq!(&writer.get_ref().buffer, b"Line 1\nPartial"); | |
912 | } | |
913 | ||
914 | /// LineWriter has a custom `write_all`; make sure it works correctly | |
915 | #[test] | |
916 | fn line_write_all() { | |
917 | let writer = ProgrammableSink { | |
918 | // Only write 5 bytes at a time | |
919 | accept_prefix: Some(5), | |
920 | ..Default::default() | |
921 | }; | |
922 | let mut writer = LineWriter::new(writer); | |
923 | ||
924 | writer.write_all(b"Line 1\nLine 2\nLine 3\nLine 4\nPartial").unwrap(); | |
925 | assert_eq!(&writer.get_ref().buffer, b"Line 1\nLine 2\nLine 3\nLine 4\n"); | |
926 | writer.write_all(b" Line 5\n").unwrap(); | |
927 | assert_eq!( | |
928 | writer.get_ref().buffer.as_slice(), | |
929 | b"Line 1\nLine 2\nLine 3\nLine 4\nPartial Line 5\n".as_ref(), | |
930 | ); | |
931 | } | |
932 | ||
933 | #[test] | |
934 | fn line_write_all_error() { | |
935 | let writer = ProgrammableSink { | |
936 | // Only accept up to 3 writes of up to 5 bytes each | |
937 | accept_prefix: Some(5), | |
938 | max_writes: Some(3), | |
939 | ..Default::default() | |
940 | }; | |
941 | ||
942 | let mut writer = LineWriter::new(writer); | |
943 | let res = writer.write_all(b"Line 1\nLine 2\nLine 3\nLine 4\nPartial"); | |
944 | assert!(res.is_err()); | |
945 | // An error from write_all leaves everything in an indeterminate state, | |
946 | // so there's nothing else to test here | |
947 | } | |
948 | ||
949 | /// Under certain circumstances, the old implementation of LineWriter | |
950 | /// would try to buffer "to the last newline" but be forced to buffer | |
951 | /// less than that, leading to inappropriate partial line writes. | |
952 | /// Regression test for that issue. | |
953 | #[test] | |
954 | fn partial_multiline_buffering() { | |
955 | let writer = ProgrammableSink { | |
956 | // Write only up to 5 bytes at a time | |
957 | accept_prefix: Some(5), | |
958 | ..Default::default() | |
959 | }; | |
960 | ||
961 | let mut writer = LineWriter::with_capacity(10, writer); | |
962 | ||
963 | let content = b"AAAAABBBBB\nCCCCDDDDDD\nEEE"; | |
964 | ||
965 | // When content is written, LineWriter will try to write blocks A, B, | |
966 | // C, and D. Only block A will succeed. Under the old behavior, LineWriter | |
967 | // would then try to buffer B, C and D, but because its capacity is 10, | |
968 | // it will only be able to buffer B and C. We don't want to buffer | |
969 | // partial lines concurrent with whole lines, so the correct behavior | |
970 | // is to buffer only block B (out to the newline) | |
971 | assert_eq!(writer.write(content).unwrap(), 11); | |
972 | assert_eq!(writer.get_ref().buffer, *b"AAAAA"); | |
973 | ||
974 | writer.flush().unwrap(); | |
975 | assert_eq!(writer.get_ref().buffer, *b"AAAAABBBBB\n"); | |
976 | } | |
977 | ||
978 | /// Same as test_partial_multiline_buffering, but in the event NO full lines | |
979 | /// fit in the buffer, just buffer as much as possible | |
980 | #[test] | |
981 | fn partial_multiline_buffering_without_full_line() { | |
982 | let writer = ProgrammableSink { | |
983 | // Write only up to 5 bytes at a time | |
984 | accept_prefix: Some(5), | |
985 | ..Default::default() | |
986 | }; | |
987 | ||
988 | let mut writer = LineWriter::with_capacity(5, writer); | |
989 | ||
990 | let content = b"AAAAABBBBBBBBBB\nCCCCC\nDDDDD"; | |
991 | ||
992 | // When content is written, LineWriter will try to write blocks A, B, | |
993 | // and C. Only block A will succeed. Under the old behavior, LineWriter | |
994 | // would then try to buffer B and C, but because its capacity is 5, | |
995 | // it will only be able to buffer part of B. Because it's not possible | |
996 | // for it to buffer any complete lines, it should buffer as much of B as | |
997 | // possible | |
998 | assert_eq!(writer.write(content).unwrap(), 10); | |
999 | assert_eq!(writer.get_ref().buffer, *b"AAAAA"); | |
1000 | ||
1001 | writer.flush().unwrap(); | |
1002 | assert_eq!(writer.get_ref().buffer, *b"AAAAABBBBB"); | |
1003 | } | |
1004 | ||
1005 | #[derive(Debug, Clone, PartialEq, Eq)] | |
1006 | enum RecordedEvent { | |
1007 | Write(String), | |
1008 | Flush, | |
1009 | } | |
1010 | ||
1011 | #[derive(Debug, Clone, Default)] | |
1012 | struct WriteRecorder { | |
1013 | pub events: Vec<RecordedEvent>, | |
1014 | } | |
1015 | ||
1016 | impl Write for WriteRecorder { | |
1017 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { | |
1018 | use crate::str::from_utf8; | |
1019 | ||
1020 | self.events.push(RecordedEvent::Write(from_utf8(buf).unwrap().to_string())); | |
1021 | Ok(buf.len()) | |
1022 | } | |
1023 | ||
1024 | fn flush(&mut self) -> io::Result<()> { | |
1025 | self.events.push(RecordedEvent::Flush); | |
1026 | Ok(()) | |
1027 | } | |
1028 | } | |
1029 | ||
1030 | /// Test that a normal, formatted writeln only results in a single write | |
1031 | /// call to the underlying writer. A naive implementation of | |
1032 | /// LineWriter::write_all results in two writes: one of the buffered data, | |
1033 | /// and another of the final substring in the formatted set | |
1034 | #[test] | |
1035 | fn single_formatted_write() { | |
1036 | let writer = WriteRecorder::default(); | |
1037 | let mut writer = LineWriter::new(writer); | |
1038 | ||
1039 | // Under a naive implementation of LineWriter, this will result in two | |
1040 | // writes: "hello, world" and "!\n", because write() has to flush the | |
1041 | // buffer before attempting to write the last "!\n". write_all shouldn't | |
1042 | // have this limitation. | |
1043 | writeln!(&mut writer, "{}, {}!", "hello", "world").unwrap(); | |
1044 | assert_eq!(writer.get_ref().events, [RecordedEvent::Write("hello, world!\n".to_string())]); | |
1045 | } | |
f2b60f7d FG |
1046 | |
1047 | #[test] | |
1048 | fn bufreader_full_initialize() { | |
1049 | struct OneByteReader; | |
1050 | impl Read for OneByteReader { | |
1051 | fn read(&mut self, buf: &mut [u8]) -> crate::io::Result<usize> { | |
1052 | if buf.len() > 0 { | |
1053 | buf[0] = 0; | |
1054 | Ok(1) | |
1055 | } else { | |
1056 | Ok(0) | |
1057 | } | |
1058 | } | |
1059 | } | |
1060 | let mut reader = BufReader::new(OneByteReader); | |
1061 | // Nothing is initialized yet. | |
1062 | assert_eq!(reader.initialized(), 0); | |
1063 | ||
1064 | let buf = reader.fill_buf().unwrap(); | |
1065 | // We read one byte... | |
1066 | assert_eq!(buf.len(), 1); | |
1067 | // But we initialized the whole buffer! | |
1068 | assert_eq!(reader.initialized(), reader.capacity()); | |
1069 | } | |
1f0639a9 FG |
1070 | |
1071 | /// This is a regression test for https://github.com/rust-lang/rust/issues/127584. | |
1072 | #[test] | |
1073 | fn bufwriter_aliasing() { | |
1074 | use crate::io::{BufWriter, Cursor}; | |
1075 | let mut v = vec![0; 1024]; | |
1076 | let c = Cursor::new(&mut v); | |
1077 | let w = BufWriter::new(Box::new(c)); | |
1078 | let _ = w.into_parts(); | |
1079 | } |