about summary refs log tree commit diff
path: root/library/std/src/io
diff options
context:
space:
mode:
authorLzu Tao <taolzu@gmail.com>2020-08-27 13:45:01 +0000
committerLzu Tao <taolzu@gmail.com>2020-08-31 02:56:59 +0000
commita4e926daeeaedc9178846711daf1f4cb6ce505fb (patch)
tree0c830f716f6f5ad17736d459f5de9b9199006d54 /library/std/src/io
parentdb6cbfc49ca655739ba8caae43ebd7c77c8a1179 (diff)
downloadrust-a4e926daeeaedc9178846711daf1f4cb6ce505fb.tar.gz
rust-a4e926daeeaedc9178846711daf1f4cb6ce505fb.zip
std: move "mod tests/benches" to separate files
Also doing fmt inplace as requested.
Diffstat (limited to 'library/std/src/io')
-rw-r--r--library/std/src/io/buffered.rs923
-rw-r--r--library/std/src/io/buffered/tests.rs916
-rw-r--r--library/std/src/io/cursor.rs531
-rw-r--r--library/std/src/io/cursor/tests.rs516
-rw-r--r--library/std/src/io/error.rs60
-rw-r--r--library/std/src/io/error/tests.rs53
-rw-r--r--library/std/src/io/impls.rs64
-rw-r--r--library/std/src/io/impls/tests.rs57
-rw-r--r--library/std/src/io/mod.rs501
-rw-r--r--library/std/src/io/stdio.rs54
-rw-r--r--library/std/src/io/stdio/tests.rs47
-rw-r--r--library/std/src/io/tests.rs494
-rw-r--r--library/std/src/io/util.rs52
-rw-r--r--library/std/src/io/util/tests.rs45
14 files changed, 2149 insertions, 2164 deletions
diff --git a/library/std/src/io/buffered.rs b/library/std/src/io/buffered.rs
index ec3c69dd616..5ad8f8132e4 100644
--- a/library/std/src/io/buffered.rs
+++ b/library/std/src/io/buffered.rs
@@ -1,5 +1,8 @@
 //! Buffering wrappers for I/O traits
 
+#[cfg(test)]
+mod tests;
+
 use crate::io::prelude::*;
 
 use crate::cmp;
@@ -1388,923 +1391,3 @@ where
             .finish()
     }
 }
-
-#[cfg(test)]
-mod tests {
-    use crate::io::prelude::*;
-    use crate::io::{self, BufReader, BufWriter, ErrorKind, IoSlice, LineWriter, SeekFrom};
-    use crate::sync::atomic::{AtomicUsize, Ordering};
-    use crate::thread;
-
-    /// A dummy reader intended at testing short-reads propagation.
-    pub struct ShortReader {
-        lengths: Vec<usize>,
-    }
-
-    // FIXME: rustfmt and tidy disagree about the correct formatting of this
-    // function. This leads to issues for users with editors configured to
-    // rustfmt-on-save.
-    impl Read for ShortReader {
-        fn read(&mut self, _: &mut [u8]) -> io::Result<usize> {
-            if self.lengths.is_empty() { Ok(0) } else { Ok(self.lengths.remove(0)) }
-        }
-    }
-
-    #[test]
-    fn test_buffered_reader() {
-        let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4];
-        let mut reader = BufReader::with_capacity(2, inner);
-
-        let mut buf = [0, 0, 0];
-        let nread = reader.read(&mut buf);
-        assert_eq!(nread.unwrap(), 3);
-        assert_eq!(buf, [5, 6, 7]);
-        assert_eq!(reader.buffer(), []);
-
-        let mut buf = [0, 0];
-        let nread = reader.read(&mut buf);
-        assert_eq!(nread.unwrap(), 2);
-        assert_eq!(buf, [0, 1]);
-        assert_eq!(reader.buffer(), []);
-
-        let mut buf = [0];
-        let nread = reader.read(&mut buf);
-        assert_eq!(nread.unwrap(), 1);
-        assert_eq!(buf, [2]);
-        assert_eq!(reader.buffer(), [3]);
-
-        let mut buf = [0, 0, 0];
-        let nread = reader.read(&mut buf);
-        assert_eq!(nread.unwrap(), 1);
-        assert_eq!(buf, [3, 0, 0]);
-        assert_eq!(reader.buffer(), []);
-
-        let nread = reader.read(&mut buf);
-        assert_eq!(nread.unwrap(), 1);
-        assert_eq!(buf, [4, 0, 0]);
-        assert_eq!(reader.buffer(), []);
-
-        assert_eq!(reader.read(&mut buf).unwrap(), 0);
-    }
-
-    #[test]
-    fn test_buffered_reader_seek() {
-        let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4];
-        let mut reader = BufReader::with_capacity(2, io::Cursor::new(inner));
-
-        assert_eq!(reader.seek(SeekFrom::Start(3)).ok(), Some(3));
-        assert_eq!(reader.fill_buf().ok(), Some(&[0, 1][..]));
-        assert_eq!(reader.seek(SeekFrom::Current(0)).ok(), Some(3));
-        assert_eq!(reader.fill_buf().ok(), Some(&[0, 1][..]));
-        assert_eq!(reader.seek(SeekFrom::Current(1)).ok(), Some(4));
-        assert_eq!(reader.fill_buf().ok(), Some(&[1, 2][..]));
-        reader.consume(1);
-        assert_eq!(reader.seek(SeekFrom::Current(-2)).ok(), Some(3));
-    }
-
-    #[test]
-    fn test_buffered_reader_seek_relative() {
-        let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4];
-        let mut reader = BufReader::with_capacity(2, io::Cursor::new(inner));
-
-        assert!(reader.seek_relative(3).is_ok());
-        assert_eq!(reader.fill_buf().ok(), Some(&[0, 1][..]));
-        assert!(reader.seek_relative(0).is_ok());
-        assert_eq!(reader.fill_buf().ok(), Some(&[0, 1][..]));
-        assert!(reader.seek_relative(1).is_ok());
-        assert_eq!(reader.fill_buf().ok(), Some(&[1][..]));
-        assert!(reader.seek_relative(-1).is_ok());
-        assert_eq!(reader.fill_buf().ok(), Some(&[0, 1][..]));
-        assert!(reader.seek_relative(2).is_ok());
-        assert_eq!(reader.fill_buf().ok(), Some(&[2, 3][..]));
-    }
-
-    #[test]
-    fn test_buffered_reader_invalidated_after_read() {
-        let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4];
-        let mut reader = BufReader::with_capacity(3, io::Cursor::new(inner));
-
-        assert_eq!(reader.fill_buf().ok(), Some(&[5, 6, 7][..]));
-        reader.consume(3);
-
-        let mut buffer = [0, 0, 0, 0, 0];
-        assert_eq!(reader.read(&mut buffer).ok(), Some(5));
-        assert_eq!(buffer, [0, 1, 2, 3, 4]);
-
-        assert!(reader.seek_relative(-2).is_ok());
-        let mut buffer = [0, 0];
-        assert_eq!(reader.read(&mut buffer).ok(), Some(2));
-        assert_eq!(buffer, [3, 4]);
-    }
-
-    #[test]
-    fn test_buffered_reader_invalidated_after_seek() {
-        let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4];
-        let mut reader = BufReader::with_capacity(3, io::Cursor::new(inner));
-
-        assert_eq!(reader.fill_buf().ok(), Some(&[5, 6, 7][..]));
-        reader.consume(3);
-
-        assert!(reader.seek(SeekFrom::Current(5)).is_ok());
-
-        assert!(reader.seek_relative(-2).is_ok());
-        let mut buffer = [0, 0];
-        assert_eq!(reader.read(&mut buffer).ok(), Some(2));
-        assert_eq!(buffer, [3, 4]);
-    }
-
-    #[test]
-    fn test_buffered_reader_seek_underflow() {
-        // gimmick reader that yields its position modulo 256 for each byte
-        struct PositionReader {
-            pos: u64,
-        }
-        impl Read for PositionReader {
-            fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-                let len = buf.len();
-                for x in buf {
-                    *x = self.pos as u8;
-                    self.pos = self.pos.wrapping_add(1);
-                }
-                Ok(len)
-            }
-        }
-        impl Seek for PositionReader {
-            fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
-                match pos {
-                    SeekFrom::Start(n) => {
-                        self.pos = n;
-                    }
-                    SeekFrom::Current(n) => {
-                        self.pos = self.pos.wrapping_add(n as u64);
-                    }
-                    SeekFrom::End(n) => {
-                        self.pos = u64::MAX.wrapping_add(n as u64);
-                    }
-                }
-                Ok(self.pos)
-            }
-        }
-
-        let mut reader = BufReader::with_capacity(5, PositionReader { pos: 0 });
-        assert_eq!(reader.fill_buf().ok(), Some(&[0, 1, 2, 3, 4][..]));
-        assert_eq!(reader.seek(SeekFrom::End(-5)).ok(), Some(u64::MAX - 5));
-        assert_eq!(reader.fill_buf().ok().map(|s| s.len()), Some(5));
-        // the following seek will require two underlying seeks
-        let expected = 9223372036854775802;
-        assert_eq!(reader.seek(SeekFrom::Current(i64::MIN)).ok(), Some(expected));
-        assert_eq!(reader.fill_buf().ok().map(|s| s.len()), Some(5));
-        // seeking to 0 should empty the buffer.
-        assert_eq!(reader.seek(SeekFrom::Current(0)).ok(), Some(expected));
-        assert_eq!(reader.get_ref().pos, expected);
-    }
-
-    #[test]
-    fn test_buffered_reader_seek_underflow_discard_buffer_between_seeks() {
-        // gimmick reader that returns Err after first seek
-        struct ErrAfterFirstSeekReader {
-            first_seek: bool,
-        }
-        impl Read for ErrAfterFirstSeekReader {
-            fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-                for x in &mut *buf {
-                    *x = 0;
-                }
-                Ok(buf.len())
-            }
-        }
-        impl Seek for ErrAfterFirstSeekReader {
-            fn seek(&mut self, _: SeekFrom) -> io::Result<u64> {
-                if self.first_seek {
-                    self.first_seek = false;
-                    Ok(0)
-                } else {
-                    Err(io::Error::new(io::ErrorKind::Other, "oh no!"))
-                }
-            }
-        }
-
-        let mut reader = BufReader::with_capacity(5, ErrAfterFirstSeekReader { first_seek: true });
-        assert_eq!(reader.fill_buf().ok(), Some(&[0, 0, 0, 0, 0][..]));
-
-        // The following seek will require two underlying seeks.  The first will
-        // succeed but the second will fail.  This should still invalidate the
-        // buffer.
-        assert!(reader.seek(SeekFrom::Current(i64::MIN)).is_err());
-        assert_eq!(reader.buffer().len(), 0);
-    }
-
-    #[test]
-    fn test_buffered_writer() {
-        let inner = Vec::new();
-        let mut writer = BufWriter::with_capacity(2, inner);
-
-        writer.write(&[0, 1]).unwrap();
-        assert_eq!(writer.buffer(), []);
-        assert_eq!(*writer.get_ref(), [0, 1]);
-
-        writer.write(&[2]).unwrap();
-        assert_eq!(writer.buffer(), [2]);
-        assert_eq!(*writer.get_ref(), [0, 1]);
-
-        writer.write(&[3]).unwrap();
-        assert_eq!(writer.buffer(), [2, 3]);
-        assert_eq!(*writer.get_ref(), [0, 1]);
-
-        writer.flush().unwrap();
-        assert_eq!(writer.buffer(), []);
-        assert_eq!(*writer.get_ref(), [0, 1, 2, 3]);
-
-        writer.write(&[4]).unwrap();
-        writer.write(&[5]).unwrap();
-        assert_eq!(writer.buffer(), [4, 5]);
-        assert_eq!(*writer.get_ref(), [0, 1, 2, 3]);
-
-        writer.write(&[6]).unwrap();
-        assert_eq!(writer.buffer(), [6]);
-        assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5]);
-
-        writer.write(&[7, 8]).unwrap();
-        assert_eq!(writer.buffer(), []);
-        assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8]);
-
-        writer.write(&[9, 10, 11]).unwrap();
-        assert_eq!(writer.buffer(), []);
-        assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
-
-        writer.flush().unwrap();
-        assert_eq!(writer.buffer(), []);
-        assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
-    }
-
-    #[test]
-    fn test_buffered_writer_inner_flushes() {
-        let mut w = BufWriter::with_capacity(3, Vec::new());
-        w.write(&[0, 1]).unwrap();
-        assert_eq!(*w.get_ref(), []);
-        let w = w.into_inner().unwrap();
-        assert_eq!(w, [0, 1]);
-    }
-
-    #[test]
-    fn test_buffered_writer_seek() {
-        let mut w = BufWriter::with_capacity(3, io::Cursor::new(Vec::new()));
-        w.write_all(&[0, 1, 2, 3, 4, 5]).unwrap();
-        w.write_all(&[6, 7]).unwrap();
-        assert_eq!(w.seek(SeekFrom::Current(0)).ok(), Some(8));
-        assert_eq!(&w.get_ref().get_ref()[..], &[0, 1, 2, 3, 4, 5, 6, 7][..]);
-        assert_eq!(w.seek(SeekFrom::Start(2)).ok(), Some(2));
-        w.write_all(&[8, 9]).unwrap();
-        assert_eq!(&w.into_inner().unwrap().into_inner()[..], &[0, 1, 8, 9, 4, 5, 6, 7]);
-    }
-
-    #[test]
-    fn test_read_until() {
-        let inner: &[u8] = &[0, 1, 2, 1, 0];
-        let mut reader = BufReader::with_capacity(2, inner);
-        let mut v = Vec::new();
-        reader.read_until(0, &mut v).unwrap();
-        assert_eq!(v, [0]);
-        v.truncate(0);
-        reader.read_until(2, &mut v).unwrap();
-        assert_eq!(v, [1, 2]);
-        v.truncate(0);
-        reader.read_until(1, &mut v).unwrap();
-        assert_eq!(v, [1]);
-        v.truncate(0);
-        reader.read_until(8, &mut v).unwrap();
-        assert_eq!(v, [0]);
-        v.truncate(0);
-        reader.read_until(9, &mut v).unwrap();
-        assert_eq!(v, []);
-    }
-
-    #[test]
-    fn test_line_buffer() {
-        let mut writer = LineWriter::new(Vec::new());
-        writer.write(&[0]).unwrap();
-        assert_eq!(*writer.get_ref(), []);
-        writer.write(&[1]).unwrap();
-        assert_eq!(*writer.get_ref(), []);
-        writer.flush().unwrap();
-        assert_eq!(*writer.get_ref(), [0, 1]);
-        writer.write(&[0, b'\n', 1, b'\n', 2]).unwrap();
-        assert_eq!(*writer.get_ref(), [0, 1, 0, b'\n', 1, b'\n']);
-        writer.flush().unwrap();
-        assert_eq!(*writer.get_ref(), [0, 1, 0, b'\n', 1, b'\n', 2]);
-        writer.write(&[3, b'\n']).unwrap();
-        assert_eq!(*writer.get_ref(), [0, 1, 0, b'\n', 1, b'\n', 2, 3, b'\n']);
-    }
-
-    #[test]
-    fn test_read_line() {
-        let in_buf: &[u8] = b"a\nb\nc";
-        let mut reader = BufReader::with_capacity(2, in_buf);
-        let mut s = String::new();
-        reader.read_line(&mut s).unwrap();
-        assert_eq!(s, "a\n");
-        s.truncate(0);
-        reader.read_line(&mut s).unwrap();
-        assert_eq!(s, "b\n");
-        s.truncate(0);
-        reader.read_line(&mut s).unwrap();
-        assert_eq!(s, "c");
-        s.truncate(0);
-        reader.read_line(&mut s).unwrap();
-        assert_eq!(s, "");
-    }
-
-    #[test]
-    fn test_lines() {
-        let in_buf: &[u8] = b"a\nb\nc";
-        let reader = BufReader::with_capacity(2, in_buf);
-        let mut it = reader.lines();
-        assert_eq!(it.next().unwrap().unwrap(), "a".to_string());
-        assert_eq!(it.next().unwrap().unwrap(), "b".to_string());
-        assert_eq!(it.next().unwrap().unwrap(), "c".to_string());
-        assert!(it.next().is_none());
-    }
-
-    #[test]
-    fn test_short_reads() {
-        let inner = ShortReader { lengths: vec![0, 1, 2, 0, 1, 0] };
-        let mut reader = BufReader::new(inner);
-        let mut buf = [0, 0];
-        assert_eq!(reader.read(&mut buf).unwrap(), 0);
-        assert_eq!(reader.read(&mut buf).unwrap(), 1);
-        assert_eq!(reader.read(&mut buf).unwrap(), 2);
-        assert_eq!(reader.read(&mut buf).unwrap(), 0);
-        assert_eq!(reader.read(&mut buf).unwrap(), 1);
-        assert_eq!(reader.read(&mut buf).unwrap(), 0);
-        assert_eq!(reader.read(&mut buf).unwrap(), 0);
-    }
-
-    #[test]
-    #[should_panic]
-    fn dont_panic_in_drop_on_panicked_flush() {
-        struct FailFlushWriter;
-
-        impl Write for FailFlushWriter {
-            fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-                Ok(buf.len())
-            }
-            fn flush(&mut self) -> io::Result<()> {
-                Err(io::Error::last_os_error())
-            }
-        }
-
-        let writer = FailFlushWriter;
-        let _writer = BufWriter::new(writer);
-
-        // If writer panics *again* due to the flush error then the process will
-        // abort.
-        panic!();
-    }
-
-    #[test]
-    #[cfg_attr(target_os = "emscripten", ignore)]
-    fn panic_in_write_doesnt_flush_in_drop() {
-        static WRITES: AtomicUsize = AtomicUsize::new(0);
-
-        struct PanicWriter;
-
-        impl Write for PanicWriter {
-            fn write(&mut self, _: &[u8]) -> io::Result<usize> {
-                WRITES.fetch_add(1, Ordering::SeqCst);
-                panic!();
-            }
-            fn flush(&mut self) -> io::Result<()> {
-                Ok(())
-            }
-        }
-
-        thread::spawn(|| {
-            let mut writer = BufWriter::new(PanicWriter);
-            let _ = writer.write(b"hello world");
-            let _ = writer.flush();
-        })
-        .join()
-        .unwrap_err();
-
-        assert_eq!(WRITES.load(Ordering::SeqCst), 1);
-    }
-
-    #[bench]
-    fn bench_buffered_reader(b: &mut test::Bencher) {
-        b.iter(|| BufReader::new(io::empty()));
-    }
-
-    #[bench]
-    fn bench_buffered_writer(b: &mut test::Bencher) {
-        b.iter(|| BufWriter::new(io::sink()));
-    }
-
-    /// A simple `Write` target, designed to be wrapped by `LineWriter` /
-    /// `BufWriter` / etc, that can have its `write` & `flush` behavior
-    /// configured
-    #[derive(Default, Clone)]
-    struct ProgrammableSink {
-        // Writes append to this slice
-        pub buffer: Vec<u8>,
-
-        // Flush sets this flag
-        pub flushed: bool,
-
-        // If true, writes will always be an error
-        pub always_write_error: bool,
-
-        // If true, flushes will always be an error
-        pub always_flush_error: bool,
-
-        // If set, only up to this number of bytes will be written in a single
-        // call to `write`
-        pub accept_prefix: Option<usize>,
-
-        // If set, counts down with each write, and writes return an error
-        // when it hits 0
-        pub max_writes: Option<usize>,
-
-        // If set, attempting to write when max_writes == Some(0) will be an
-        // error; otherwise, it will return Ok(0).
-        pub error_after_max_writes: bool,
-    }
-
-    impl Write for ProgrammableSink {
-        fn write(&mut self, data: &[u8]) -> io::Result<usize> {
-            if self.always_write_error {
-                return Err(io::Error::new(io::ErrorKind::Other, "test - always_write_error"));
-            }
-
-            match self.max_writes {
-                Some(0) if self.error_after_max_writes => {
-                    return Err(io::Error::new(io::ErrorKind::Other, "test - max_writes"));
-                }
-                Some(0) => return Ok(0),
-                Some(ref mut count) => *count -= 1,
-                None => {}
-            }
-
-            let len = match self.accept_prefix {
-                None => data.len(),
-                Some(prefix) => data.len().min(prefix),
-            };
-
-            let data = &data[..len];
-            self.buffer.extend_from_slice(data);
-
-            Ok(len)
-        }
-
-        fn flush(&mut self) -> io::Result<()> {
-            if self.always_flush_error {
-                Err(io::Error::new(io::ErrorKind::Other, "test - always_flush_error"))
-            } else {
-                self.flushed = true;
-                Ok(())
-            }
-        }
-    }
-
-    /// Previously the `LineWriter` could successfully write some bytes but
-    /// then fail to report that it has done so. Additionally, an erroneous
-    /// flush after a successful write was permanently ignored.
-    ///
-    /// Test that a line writer correctly reports the number of written bytes,
-    /// and that it attempts to flush buffered lines from previous writes
-    /// before processing new data
-    ///
-    /// Regression test for #37807
-    #[test]
-    fn erroneous_flush_retried() {
-        let writer = ProgrammableSink {
-            // Only write up to 4 bytes at a time
-            accept_prefix: Some(4),
-
-            // Accept the first two writes, then error the others
-            max_writes: Some(2),
-            error_after_max_writes: true,
-
-            ..Default::default()
-        };
-
-        // This should write the first 4 bytes. The rest will be buffered, out
-        // to the last newline.
-        let mut writer = LineWriter::new(writer);
-        assert_eq!(writer.write(b"a\nb\nc\nd\ne").unwrap(), 8);
-
-        // This write should attempt to flush "c\nd\n", then buffer "e". No
-        // errors should happen here because no further writes should be
-        // attempted against `writer`.
-        assert_eq!(writer.write(b"e").unwrap(), 1);
-        assert_eq!(&writer.get_ref().buffer, b"a\nb\nc\nd\n");
-    }
-
-    #[test]
-    fn line_vectored() {
-        let mut a = LineWriter::new(Vec::new());
-        assert_eq!(
-            a.write_vectored(&[
-                IoSlice::new(&[]),
-                IoSlice::new(b"\n"),
-                IoSlice::new(&[]),
-                IoSlice::new(b"a"),
-            ])
-            .unwrap(),
-            2,
-        );
-        assert_eq!(a.get_ref(), b"\n");
-
-        assert_eq!(
-            a.write_vectored(&[
-                IoSlice::new(&[]),
-                IoSlice::new(b"b"),
-                IoSlice::new(&[]),
-                IoSlice::new(b"a"),
-                IoSlice::new(&[]),
-                IoSlice::new(b"c"),
-            ])
-            .unwrap(),
-            3,
-        );
-        assert_eq!(a.get_ref(), b"\n");
-        a.flush().unwrap();
-        assert_eq!(a.get_ref(), b"\nabac");
-        assert_eq!(a.write_vectored(&[]).unwrap(), 0);
-        assert_eq!(
-            a.write_vectored(&[
-                IoSlice::new(&[]),
-                IoSlice::new(&[]),
-                IoSlice::new(&[]),
-                IoSlice::new(&[]),
-            ])
-            .unwrap(),
-            0,
-        );
-        assert_eq!(a.write_vectored(&[IoSlice::new(b"a\nb"),]).unwrap(), 3);
-        assert_eq!(a.get_ref(), b"\nabaca\nb");
-    }
-
-    #[test]
-    fn line_vectored_partial_and_errors() {
-        use crate::collections::VecDeque;
-
-        enum Call {
-            Write { inputs: Vec<&'static [u8]>, output: io::Result<usize> },
-            Flush { output: io::Result<()> },
-        }
-
-        #[derive(Default)]
-        struct Writer {
-            calls: VecDeque<Call>,
-        }
-
-        impl Write for Writer {
-            fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-                self.write_vectored(&[IoSlice::new(buf)])
-            }
-
-            fn write_vectored(&mut self, buf: &[IoSlice<'_>]) -> io::Result<usize> {
-                match self.calls.pop_front().expect("unexpected call to write") {
-                    Call::Write { inputs, output } => {
-                        assert_eq!(inputs, buf.iter().map(|b| &**b).collect::<Vec<_>>());
-                        output
-                    }
-                    Call::Flush { .. } => panic!("unexpected call to write; expected a flush"),
-                }
-            }
-
-            fn is_write_vectored(&self) -> bool {
-                true
-            }
-
-            fn flush(&mut self) -> io::Result<()> {
-                match self.calls.pop_front().expect("Unexpected call to flush") {
-                    Call::Flush { output } => output,
-                    Call::Write { .. } => panic!("unexpected call to flush; expected a write"),
-                }
-            }
-        }
-
-        impl Drop for Writer {
-            fn drop(&mut self) {
-                if !thread::panicking() {
-                    assert_eq!(self.calls.len(), 0);
-                }
-            }
-        }
-
-        // partial writes keep going
-        let mut a = LineWriter::new(Writer::default());
-        a.write_vectored(&[IoSlice::new(&[]), IoSlice::new(b"abc")]).unwrap();
-
-        a.get_mut().calls.push_back(Call::Write { inputs: vec![b"abc"], output: Ok(1) });
-        a.get_mut().calls.push_back(Call::Write { inputs: vec![b"bc"], output: Ok(2) });
-        a.get_mut().calls.push_back(Call::Write { inputs: vec![b"x", b"\n"], output: Ok(2) });
-
-        a.write_vectored(&[IoSlice::new(b"x"), IoSlice::new(b"\n")]).unwrap();
-
-        a.get_mut().calls.push_back(Call::Flush { output: Ok(()) });
-        a.flush().unwrap();
-
-        // erroneous writes stop and don't write more
-        a.get_mut().calls.push_back(Call::Write { inputs: vec![b"x", b"\na"], output: Err(err()) });
-        a.get_mut().calls.push_back(Call::Flush { output: Ok(()) });
-        assert!(a.write_vectored(&[IoSlice::new(b"x"), IoSlice::new(b"\na")]).is_err());
-        a.flush().unwrap();
-
-        fn err() -> io::Error {
-            io::Error::new(io::ErrorKind::Other, "x")
-        }
-    }
-
-    /// Test that, in cases where vectored writing is not enabled, the
-    /// LineWriter uses the normal `write` call, which more-correctly handles
-    /// partial lines
-    #[test]
-    fn line_vectored_ignored() {
-        let writer = ProgrammableSink::default();
-        let mut writer = LineWriter::new(writer);
-
-        let content = [
-            IoSlice::new(&[]),
-            IoSlice::new(b"Line 1\nLine"),
-            IoSlice::new(b" 2\nLine 3\nL"),
-            IoSlice::new(&[]),
-            IoSlice::new(&[]),
-            IoSlice::new(b"ine 4"),
-            IoSlice::new(b"\nLine 5\n"),
-        ];
-
-        let count = writer.write_vectored(&content).unwrap();
-        assert_eq!(count, 11);
-        assert_eq!(&writer.get_ref().buffer, b"Line 1\n");
-
-        let count = writer.write_vectored(&content[2..]).unwrap();
-        assert_eq!(count, 11);
-        assert_eq!(&writer.get_ref().buffer, b"Line 1\nLine 2\nLine 3\n");
-
-        let count = writer.write_vectored(&content[5..]).unwrap();
-        assert_eq!(count, 5);
-        assert_eq!(&writer.get_ref().buffer, b"Line 1\nLine 2\nLine 3\n");
-
-        let count = writer.write_vectored(&content[6..]).unwrap();
-        assert_eq!(count, 8);
-        assert_eq!(
-            writer.get_ref().buffer.as_slice(),
-            b"Line 1\nLine 2\nLine 3\nLine 4\nLine 5\n".as_ref()
-        );
-    }
-
-    /// Test that, given this input:
-    ///
-    /// Line 1\n
-    /// Line 2\n
-    /// Line 3\n
-    /// Line 4
-    ///
-    /// And given a result that only writes to midway through Line 2
-    ///
-    /// That only up to the end of Line 3 is buffered
-    ///
-    /// This behavior is desirable because it prevents flushing partial lines
-    #[test]
-    fn partial_write_buffers_line() {
-        let writer = ProgrammableSink { accept_prefix: Some(13), ..Default::default() };
-        let mut writer = LineWriter::new(writer);
-
-        assert_eq!(writer.write(b"Line 1\nLine 2\nLine 3\nLine4").unwrap(), 21);
-        assert_eq!(&writer.get_ref().buffer, b"Line 1\nLine 2");
-
-        assert_eq!(writer.write(b"Line 4").unwrap(), 6);
-        assert_eq!(&writer.get_ref().buffer, b"Line 1\nLine 2\nLine 3\n");
-    }
-
-    /// Test that, given this input:
-    ///
-    /// Line 1\n
-    /// Line 2\n
-    /// Line 3
-    ///
-    /// And given that the full write of lines 1 and 2 was successful
-    /// That data up to Line 3 is buffered
-    #[test]
-    fn partial_line_buffered_after_line_write() {
-        let writer = ProgrammableSink::default();
-        let mut writer = LineWriter::new(writer);
-
-        assert_eq!(writer.write(b"Line 1\nLine 2\nLine 3").unwrap(), 20);
-        assert_eq!(&writer.get_ref().buffer, b"Line 1\nLine 2\n");
-
-        assert!(writer.flush().is_ok());
-        assert_eq!(&writer.get_ref().buffer, b"Line 1\nLine 2\nLine 3");
-    }
-
-    /// Test that, given a partial line that exceeds the length of
-    /// LineBuffer's buffer (that is, without a trailing newline), that that
-    /// line is written to the inner writer
-    #[test]
-    fn long_line_flushed() {
-        let writer = ProgrammableSink::default();
-        let mut writer = LineWriter::with_capacity(5, writer);
-
-        assert_eq!(writer.write(b"0123456789").unwrap(), 10);
-        assert_eq!(&writer.get_ref().buffer, b"0123456789");
-    }
-
-    /// Test that, given a very long partial line *after* successfully
-    /// flushing a complete line, that that line is buffered unconditionally,
-    /// and no additional writes take place. This assures the property that
-    /// `write` should make at-most-one attempt to write new data.
-    #[test]
-    fn line_long_tail_not_flushed() {
-        let writer = ProgrammableSink::default();
-        let mut writer = LineWriter::with_capacity(5, writer);
-
-        // Assert that Line 1\n is flushed, and 01234 is buffered
-        assert_eq!(writer.write(b"Line 1\n0123456789").unwrap(), 12);
-        assert_eq!(&writer.get_ref().buffer, b"Line 1\n");
-
-        // Because the buffer is full, this subsequent write will flush it
-        assert_eq!(writer.write(b"5").unwrap(), 1);
-        assert_eq!(&writer.get_ref().buffer, b"Line 1\n01234");
-    }
-
-    /// Test that, if an attempt to pre-flush buffered data returns Ok(0),
-    /// this is propagated as an error.
-    #[test]
-    fn line_buffer_write0_error() {
-        let writer = ProgrammableSink {
-            // Accept one write, then return Ok(0) on subsequent ones
-            max_writes: Some(1),
-
-            ..Default::default()
-        };
-        let mut writer = LineWriter::new(writer);
-
-        // This should write "Line 1\n" and buffer "Partial"
-        assert_eq!(writer.write(b"Line 1\nPartial").unwrap(), 14);
-        assert_eq!(&writer.get_ref().buffer, b"Line 1\n");
-
-        // This will attempt to flush "partial", which will return Ok(0), which
-        // needs to be an error, because we've already informed the client
-        // that we accepted the write.
-        let err = writer.write(b" Line End\n").unwrap_err();
-        assert_eq!(err.kind(), ErrorKind::WriteZero);
-        assert_eq!(&writer.get_ref().buffer, b"Line 1\n");
-    }
-
-    /// Test that, if a write returns Ok(0) after a successful pre-flush, this
-    /// is propagated as Ok(0)
-    #[test]
-    fn line_buffer_write0_normal() {
-        let writer = ProgrammableSink {
-            // Accept two writes, then return Ok(0) on subsequent ones
-            max_writes: Some(2),
-
-            ..Default::default()
-        };
-        let mut writer = LineWriter::new(writer);
-
-        // This should write "Line 1\n" and buffer "Partial"
-        assert_eq!(writer.write(b"Line 1\nPartial").unwrap(), 14);
-        assert_eq!(&writer.get_ref().buffer, b"Line 1\n");
-
-        // This will flush partial, which will succeed, but then return Ok(0)
-        // when flushing " Line End\n"
-        assert_eq!(writer.write(b" Line End\n").unwrap(), 0);
-        assert_eq!(&writer.get_ref().buffer, b"Line 1\nPartial");
-    }
-
-    /// LineWriter has a custom `write_all`; make sure it works correctly
-    #[test]
-    fn line_write_all() {
-        let writer = ProgrammableSink {
-            // Only write 5 bytes at a time
-            accept_prefix: Some(5),
-            ..Default::default()
-        };
-        let mut writer = LineWriter::new(writer);
-
-        writer.write_all(b"Line 1\nLine 2\nLine 3\nLine 4\nPartial").unwrap();
-        assert_eq!(&writer.get_ref().buffer, b"Line 1\nLine 2\nLine 3\nLine 4\n");
-        writer.write_all(b" Line 5\n").unwrap();
-        assert_eq!(
-            writer.get_ref().buffer.as_slice(),
-            b"Line 1\nLine 2\nLine 3\nLine 4\nPartial Line 5\n".as_ref(),
-        );
-    }
-
-    #[test]
-    fn line_write_all_error() {
-        let writer = ProgrammableSink {
-            // Only accept up to 3 writes of up to 5 bytes each
-            accept_prefix: Some(5),
-            max_writes: Some(3),
-            ..Default::default()
-        };
-
-        let mut writer = LineWriter::new(writer);
-        let res = writer.write_all(b"Line 1\nLine 2\nLine 3\nLine 4\nPartial");
-        assert!(res.is_err());
-        // An error from write_all leaves everything in an indeterminate state,
-        // so there's nothing else to test here
-    }
-
-    /// Under certain circumstances, the old implementation of LineWriter
-    /// would try to buffer "to the last newline" but be forced to buffer
-    /// less than that, leading to inappropriate partial line writes.
-    /// Regression test for that issue.
-    #[test]
-    fn partial_multiline_buffering() {
-        let writer = ProgrammableSink {
-            // Write only up to 5 bytes at a time
-            accept_prefix: Some(5),
-            ..Default::default()
-        };
-
-        let mut writer = LineWriter::with_capacity(10, writer);
-
-        let content = b"AAAAABBBBB\nCCCCDDDDDD\nEEE";
-
-        // When content is written, LineWriter will try to write blocks A, B,
-        // C, and D. Only block A will succeed. Under the old behavior, LineWriter
-        // would then try to buffer B, C and D, but because its capacity is 10,
-        // it will only be able to buffer B and C. We don't want to buffer
-        // partial lines concurrent with whole lines, so the correct behavior
-        // is to buffer only block B (out to the newline)
-        assert_eq!(writer.write(content).unwrap(), 11);
-        assert_eq!(writer.get_ref().buffer, *b"AAAAA");
-
-        writer.flush().unwrap();
-        assert_eq!(writer.get_ref().buffer, *b"AAAAABBBBB\n");
-    }
-
-    /// Same as test_partial_multiline_buffering, but in the event NO full lines
-    /// fit in the buffer, just buffer as much as possible
-    #[test]
-    fn partial_multiline_buffering_without_full_line() {
-        let writer = ProgrammableSink {
-            // Write only up to 5 bytes at a time
-            accept_prefix: Some(5),
-            ..Default::default()
-        };
-
-        let mut writer = LineWriter::with_capacity(5, writer);
-
-        let content = b"AAAAABBBBBBBBBB\nCCCCC\nDDDDD";
-
-        // When content is written, LineWriter will try to write blocks A, B,
-        // and C. Only block A will succeed. Under the old behavior, LineWriter
-        // would then try to buffer B and C, but because its capacity is 5,
-        // it will only be able to buffer part of B. Because it's not possible
-        // for it to buffer any complete lines, it should buffer as much of B as
-        // possible
-        assert_eq!(writer.write(content).unwrap(), 10);
-        assert_eq!(writer.get_ref().buffer, *b"AAAAA");
-
-        writer.flush().unwrap();
-        assert_eq!(writer.get_ref().buffer, *b"AAAAABBBBB");
-    }
-
-    #[derive(Debug, Clone, PartialEq, Eq)]
-    enum RecordedEvent {
-        Write(String),
-        Flush,
-    }
-
-    #[derive(Debug, Clone, Default)]
-    struct WriteRecorder {
-        pub events: Vec<RecordedEvent>,
-    }
-
-    impl Write for WriteRecorder {
-        fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-            use crate::str::from_utf8;
-
-            self.events.push(RecordedEvent::Write(from_utf8(buf).unwrap().to_string()));
-            Ok(buf.len())
-        }
-
-        fn flush(&mut self) -> io::Result<()> {
-            self.events.push(RecordedEvent::Flush);
-            Ok(())
-        }
-    }
-
-    /// Test that a normal, formatted writeln only results in a single write
-    /// call to the underlying writer. A naive implementation of
-    /// LineWriter::write_all results in two writes: one of the buffered data,
-    /// and another of the final substring in the formatted set
-    #[test]
-    fn single_formatted_write() {
-        let writer = WriteRecorder::default();
-        let mut writer = LineWriter::new(writer);
-
-        // Under a naive implementation of LineWriter, this will result in two
-        // writes: "hello, world" and "!\n", because write() has to flush the
-        // buffer before attempting to write the last "!\n". write_all shouldn't
-        // have this limitation.
-        writeln!(&mut writer, "{}, {}!", "hello", "world").unwrap();
-        assert_eq!(writer.get_ref().events, [RecordedEvent::Write("hello, world!\n".to_string())]);
-    }
-}
diff --git a/library/std/src/io/buffered/tests.rs b/library/std/src/io/buffered/tests.rs
new file mode 100644
index 00000000000..1cd02ee299a
--- /dev/null
+++ b/library/std/src/io/buffered/tests.rs
@@ -0,0 +1,916 @@
+use crate::io::prelude::*;
+use crate::io::{self, BufReader, BufWriter, ErrorKind, IoSlice, LineWriter, SeekFrom};
+use crate::sync::atomic::{AtomicUsize, Ordering};
+use crate::thread;
+
+/// A dummy reader intended at testing short-reads propagation.
+pub struct ShortReader {
+    lengths: Vec<usize>,
+}
+
+// FIXME: rustfmt and tidy disagree about the correct formatting of this
+// function. This leads to issues for users with editors configured to
+// rustfmt-on-save.
+impl Read for ShortReader {
+    fn read(&mut self, _: &mut [u8]) -> io::Result<usize> {
+        if self.lengths.is_empty() { Ok(0) } else { Ok(self.lengths.remove(0)) }
+    }
+}
+
+#[test]
+fn test_buffered_reader() {
+    let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4];
+    let mut reader = BufReader::with_capacity(2, inner);
+
+    let mut buf = [0, 0, 0];
+    let nread = reader.read(&mut buf);
+    assert_eq!(nread.unwrap(), 3);
+    assert_eq!(buf, [5, 6, 7]);
+    assert_eq!(reader.buffer(), []);
+
+    let mut buf = [0, 0];
+    let nread = reader.read(&mut buf);
+    assert_eq!(nread.unwrap(), 2);
+    assert_eq!(buf, [0, 1]);
+    assert_eq!(reader.buffer(), []);
+
+    let mut buf = [0];
+    let nread = reader.read(&mut buf);
+    assert_eq!(nread.unwrap(), 1);
+    assert_eq!(buf, [2]);
+    assert_eq!(reader.buffer(), [3]);
+
+    let mut buf = [0, 0, 0];
+    let nread = reader.read(&mut buf);
+    assert_eq!(nread.unwrap(), 1);
+    assert_eq!(buf, [3, 0, 0]);
+    assert_eq!(reader.buffer(), []);
+
+    let nread = reader.read(&mut buf);
+    assert_eq!(nread.unwrap(), 1);
+    assert_eq!(buf, [4, 0, 0]);
+    assert_eq!(reader.buffer(), []);
+
+    assert_eq!(reader.read(&mut buf).unwrap(), 0);
+}
+
+#[test]
+fn test_buffered_reader_seek() {
+    let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4];
+    let mut reader = BufReader::with_capacity(2, io::Cursor::new(inner));
+
+    assert_eq!(reader.seek(SeekFrom::Start(3)).ok(), Some(3));
+    assert_eq!(reader.fill_buf().ok(), Some(&[0, 1][..]));
+    assert_eq!(reader.seek(SeekFrom::Current(0)).ok(), Some(3));
+    assert_eq!(reader.fill_buf().ok(), Some(&[0, 1][..]));
+    assert_eq!(reader.seek(SeekFrom::Current(1)).ok(), Some(4));
+    assert_eq!(reader.fill_buf().ok(), Some(&[1, 2][..]));
+    reader.consume(1);
+    assert_eq!(reader.seek(SeekFrom::Current(-2)).ok(), Some(3));
+}
+
+#[test]
+fn test_buffered_reader_seek_relative() {
+    let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4];
+    let mut reader = BufReader::with_capacity(2, io::Cursor::new(inner));
+
+    assert!(reader.seek_relative(3).is_ok());
+    assert_eq!(reader.fill_buf().ok(), Some(&[0, 1][..]));
+    assert!(reader.seek_relative(0).is_ok());
+    assert_eq!(reader.fill_buf().ok(), Some(&[0, 1][..]));
+    assert!(reader.seek_relative(1).is_ok());
+    assert_eq!(reader.fill_buf().ok(), Some(&[1][..]));
+    assert!(reader.seek_relative(-1).is_ok());
+    assert_eq!(reader.fill_buf().ok(), Some(&[0, 1][..]));
+    assert!(reader.seek_relative(2).is_ok());
+    assert_eq!(reader.fill_buf().ok(), Some(&[2, 3][..]));
+}
+
+#[test]
+fn test_buffered_reader_invalidated_after_read() {
+    let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4];
+    let mut reader = BufReader::with_capacity(3, io::Cursor::new(inner));
+
+    assert_eq!(reader.fill_buf().ok(), Some(&[5, 6, 7][..]));
+    reader.consume(3);
+
+    let mut buffer = [0, 0, 0, 0, 0];
+    assert_eq!(reader.read(&mut buffer).ok(), Some(5));
+    assert_eq!(buffer, [0, 1, 2, 3, 4]);
+
+    assert!(reader.seek_relative(-2).is_ok());
+    let mut buffer = [0, 0];
+    assert_eq!(reader.read(&mut buffer).ok(), Some(2));
+    assert_eq!(buffer, [3, 4]);
+}
+
+#[test]
+fn test_buffered_reader_invalidated_after_seek() {
+    let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4];
+    let mut reader = BufReader::with_capacity(3, io::Cursor::new(inner));
+
+    assert_eq!(reader.fill_buf().ok(), Some(&[5, 6, 7][..]));
+    reader.consume(3);
+
+    assert!(reader.seek(SeekFrom::Current(5)).is_ok());
+
+    assert!(reader.seek_relative(-2).is_ok());
+    let mut buffer = [0, 0];
+    assert_eq!(reader.read(&mut buffer).ok(), Some(2));
+    assert_eq!(buffer, [3, 4]);
+}
+
+#[test]
+fn test_buffered_reader_seek_underflow() {
+    // gimmick reader that yields its position modulo 256 for each byte
+    struct PositionReader {
+        pos: u64,
+    }
+    impl Read for PositionReader {
+        fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+            let len = buf.len();
+            for x in buf {
+                *x = self.pos as u8;
+                self.pos = self.pos.wrapping_add(1);
+            }
+            Ok(len)
+        }
+    }
+    impl Seek for PositionReader {
+        fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
+            match pos {
+                SeekFrom::Start(n) => {
+                    self.pos = n;
+                }
+                SeekFrom::Current(n) => {
+                    self.pos = self.pos.wrapping_add(n as u64);
+                }
+                SeekFrom::End(n) => {
+                    self.pos = u64::MAX.wrapping_add(n as u64);
+                }
+            }
+            Ok(self.pos)
+        }
+    }
+
+    let mut reader = BufReader::with_capacity(5, PositionReader { pos: 0 });
+    assert_eq!(reader.fill_buf().ok(), Some(&[0, 1, 2, 3, 4][..]));
+    assert_eq!(reader.seek(SeekFrom::End(-5)).ok(), Some(u64::MAX - 5));
+    assert_eq!(reader.fill_buf().ok().map(|s| s.len()), Some(5));
+    // the following seek will require two underlying seeks
+    let expected = 9223372036854775802;
+    assert_eq!(reader.seek(SeekFrom::Current(i64::MIN)).ok(), Some(expected));
+    assert_eq!(reader.fill_buf().ok().map(|s| s.len()), Some(5));
+    // seeking to 0 should empty the buffer.
+    assert_eq!(reader.seek(SeekFrom::Current(0)).ok(), Some(expected));
+    assert_eq!(reader.get_ref().pos, expected);
+}
+
+#[test]
+fn test_buffered_reader_seek_underflow_discard_buffer_between_seeks() {
+    // gimmick reader that returns Err after first seek
+    struct ErrAfterFirstSeekReader {
+        first_seek: bool,
+    }
+    impl Read for ErrAfterFirstSeekReader {
+        fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+            for x in &mut *buf {
+                *x = 0;
+            }
+            Ok(buf.len())
+        }
+    }
+    impl Seek for ErrAfterFirstSeekReader {
+        fn seek(&mut self, _: SeekFrom) -> io::Result<u64> {
+            if self.first_seek {
+                self.first_seek = false;
+                Ok(0)
+            } else {
+                Err(io::Error::new(io::ErrorKind::Other, "oh no!"))
+            }
+        }
+    }
+
+    let mut reader = BufReader::with_capacity(5, ErrAfterFirstSeekReader { first_seek: true });
+    assert_eq!(reader.fill_buf().ok(), Some(&[0, 0, 0, 0, 0][..]));
+
+    // The following seek will require two underlying seeks.  The first will
+    // succeed but the second will fail.  This should still invalidate the
+    // buffer.
+    assert!(reader.seek(SeekFrom::Current(i64::MIN)).is_err());
+    assert_eq!(reader.buffer().len(), 0);
+}
+
+#[test]
+fn test_buffered_writer() {
+    let inner = Vec::new();
+    let mut writer = BufWriter::with_capacity(2, inner);
+
+    writer.write(&[0, 1]).unwrap();
+    assert_eq!(writer.buffer(), []);
+    assert_eq!(*writer.get_ref(), [0, 1]);
+
+    writer.write(&[2]).unwrap();
+    assert_eq!(writer.buffer(), [2]);
+    assert_eq!(*writer.get_ref(), [0, 1]);
+
+    writer.write(&[3]).unwrap();
+    assert_eq!(writer.buffer(), [2, 3]);
+    assert_eq!(*writer.get_ref(), [0, 1]);
+
+    writer.flush().unwrap();
+    assert_eq!(writer.buffer(), []);
+    assert_eq!(*writer.get_ref(), [0, 1, 2, 3]);
+
+    writer.write(&[4]).unwrap();
+    writer.write(&[5]).unwrap();
+    assert_eq!(writer.buffer(), [4, 5]);
+    assert_eq!(*writer.get_ref(), [0, 1, 2, 3]);
+
+    writer.write(&[6]).unwrap();
+    assert_eq!(writer.buffer(), [6]);
+    assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5]);
+
+    writer.write(&[7, 8]).unwrap();
+    assert_eq!(writer.buffer(), []);
+    assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8]);
+
+    writer.write(&[9, 10, 11]).unwrap();
+    assert_eq!(writer.buffer(), []);
+    assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
+
+    writer.flush().unwrap();
+    assert_eq!(writer.buffer(), []);
+    assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
+}
+
+#[test]
+fn test_buffered_writer_inner_flushes() {
+    let mut w = BufWriter::with_capacity(3, Vec::new());
+    w.write(&[0, 1]).unwrap();
+    assert_eq!(*w.get_ref(), []);
+    let w = w.into_inner().unwrap();
+    assert_eq!(w, [0, 1]);
+}
+
+#[test]
+fn test_buffered_writer_seek() {
+    let mut w = BufWriter::with_capacity(3, io::Cursor::new(Vec::new()));
+    w.write_all(&[0, 1, 2, 3, 4, 5]).unwrap();
+    w.write_all(&[6, 7]).unwrap();
+    assert_eq!(w.seek(SeekFrom::Current(0)).ok(), Some(8));
+    assert_eq!(&w.get_ref().get_ref()[..], &[0, 1, 2, 3, 4, 5, 6, 7][..]);
+    assert_eq!(w.seek(SeekFrom::Start(2)).ok(), Some(2));
+    w.write_all(&[8, 9]).unwrap();
+    assert_eq!(&w.into_inner().unwrap().into_inner()[..], &[0, 1, 8, 9, 4, 5, 6, 7]);
+}
+
+#[test]
+fn test_read_until() {
+    let inner: &[u8] = &[0, 1, 2, 1, 0];
+    let mut reader = BufReader::with_capacity(2, inner);
+    let mut v = Vec::new();
+    reader.read_until(0, &mut v).unwrap();
+    assert_eq!(v, [0]);
+    v.truncate(0);
+    reader.read_until(2, &mut v).unwrap();
+    assert_eq!(v, [1, 2]);
+    v.truncate(0);
+    reader.read_until(1, &mut v).unwrap();
+    assert_eq!(v, [1]);
+    v.truncate(0);
+    reader.read_until(8, &mut v).unwrap();
+    assert_eq!(v, [0]);
+    v.truncate(0);
+    reader.read_until(9, &mut v).unwrap();
+    assert_eq!(v, []);
+}
+
+#[test]
+fn test_line_buffer() {
+    let mut writer = LineWriter::new(Vec::new());
+    writer.write(&[0]).unwrap();
+    assert_eq!(*writer.get_ref(), []);
+    writer.write(&[1]).unwrap();
+    assert_eq!(*writer.get_ref(), []);
+    writer.flush().unwrap();
+    assert_eq!(*writer.get_ref(), [0, 1]);
+    writer.write(&[0, b'\n', 1, b'\n', 2]).unwrap();
+    assert_eq!(*writer.get_ref(), [0, 1, 0, b'\n', 1, b'\n']);
+    writer.flush().unwrap();
+    assert_eq!(*writer.get_ref(), [0, 1, 0, b'\n', 1, b'\n', 2]);
+    writer.write(&[3, b'\n']).unwrap();
+    assert_eq!(*writer.get_ref(), [0, 1, 0, b'\n', 1, b'\n', 2, 3, b'\n']);
+}
+
+#[test]
+fn test_read_line() {
+    let in_buf: &[u8] = b"a\nb\nc";
+    let mut reader = BufReader::with_capacity(2, in_buf);
+    let mut s = String::new();
+    reader.read_line(&mut s).unwrap();
+    assert_eq!(s, "a\n");
+    s.truncate(0);
+    reader.read_line(&mut s).unwrap();
+    assert_eq!(s, "b\n");
+    s.truncate(0);
+    reader.read_line(&mut s).unwrap();
+    assert_eq!(s, "c");
+    s.truncate(0);
+    reader.read_line(&mut s).unwrap();
+    assert_eq!(s, "");
+}
+
+#[test]
+fn test_lines() {
+    let in_buf: &[u8] = b"a\nb\nc";
+    let reader = BufReader::with_capacity(2, in_buf);
+    let mut it = reader.lines();
+    assert_eq!(it.next().unwrap().unwrap(), "a".to_string());
+    assert_eq!(it.next().unwrap().unwrap(), "b".to_string());
+    assert_eq!(it.next().unwrap().unwrap(), "c".to_string());
+    assert!(it.next().is_none());
+}
+
+#[test]
+fn test_short_reads() {
+    let inner = ShortReader { lengths: vec![0, 1, 2, 0, 1, 0] };
+    let mut reader = BufReader::new(inner);
+    let mut buf = [0, 0];
+    assert_eq!(reader.read(&mut buf).unwrap(), 0);
+    assert_eq!(reader.read(&mut buf).unwrap(), 1);
+    assert_eq!(reader.read(&mut buf).unwrap(), 2);
+    assert_eq!(reader.read(&mut buf).unwrap(), 0);
+    assert_eq!(reader.read(&mut buf).unwrap(), 1);
+    assert_eq!(reader.read(&mut buf).unwrap(), 0);
+    assert_eq!(reader.read(&mut buf).unwrap(), 0);
+}
+
+#[test]
+#[should_panic]
+fn dont_panic_in_drop_on_panicked_flush() {
+    struct FailFlushWriter;
+
+    impl Write for FailFlushWriter {
+        fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+            Ok(buf.len())
+        }
+        fn flush(&mut self) -> io::Result<()> {
+            Err(io::Error::last_os_error())
+        }
+    }
+
+    let writer = FailFlushWriter;
+    let _writer = BufWriter::new(writer);
+
+    // If writer panics *again* due to the flush error then the process will
+    // abort.
+    panic!();
+}
+
+#[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
+fn panic_in_write_doesnt_flush_in_drop() {
+    static WRITES: AtomicUsize = AtomicUsize::new(0);
+
+    struct PanicWriter;
+
+    impl Write for PanicWriter {
+        fn write(&mut self, _: &[u8]) -> io::Result<usize> {
+            WRITES.fetch_add(1, Ordering::SeqCst);
+            panic!();
+        }
+        fn flush(&mut self) -> io::Result<()> {
+            Ok(())
+        }
+    }
+
+    thread::spawn(|| {
+        let mut writer = BufWriter::new(PanicWriter);
+        let _ = writer.write(b"hello world");
+        let _ = writer.flush();
+    })
+    .join()
+    .unwrap_err();
+
+    assert_eq!(WRITES.load(Ordering::SeqCst), 1);
+}
+
+#[bench]
+fn bench_buffered_reader(b: &mut test::Bencher) {
+    b.iter(|| BufReader::new(io::empty()));
+}
+
+#[bench]
+fn bench_buffered_writer(b: &mut test::Bencher) {
+    b.iter(|| BufWriter::new(io::sink()));
+}
+
+/// A simple `Write` target, designed to be wrapped by `LineWriter` /
+/// `BufWriter` / etc, that can have its `write` & `flush` behavior
+/// configured
+#[derive(Default, Clone)]
+struct ProgrammableSink {
+    // Writes append to this slice
+    pub buffer: Vec<u8>,
+
+    // Flush sets this flag
+    pub flushed: bool,
+
+    // If true, writes will always be an error
+    pub always_write_error: bool,
+
+    // If true, flushes will always be an error
+    pub always_flush_error: bool,
+
+    // If set, only up to this number of bytes will be written in a single
+    // call to `write`
+    pub accept_prefix: Option<usize>,
+
+    // If set, counts down with each write, and writes return an error
+    // when it hits 0
+    pub max_writes: Option<usize>,
+
+    // If set, attempting to write when max_writes == Some(0) will be an
+    // error; otherwise, it will return Ok(0).
+    pub error_after_max_writes: bool,
+}
+
+impl Write for ProgrammableSink {
+    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
+        if self.always_write_error {
+            return Err(io::Error::new(io::ErrorKind::Other, "test - always_write_error"));
+        }
+
+        match self.max_writes {
+            Some(0) if self.error_after_max_writes => {
+                return Err(io::Error::new(io::ErrorKind::Other, "test - max_writes"));
+            }
+            Some(0) => return Ok(0),
+            Some(ref mut count) => *count -= 1,
+            None => {}
+        }
+
+        let len = match self.accept_prefix {
+            None => data.len(),
+            Some(prefix) => data.len().min(prefix),
+        };
+
+        let data = &data[..len];
+        self.buffer.extend_from_slice(data);
+
+        Ok(len)
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        if self.always_flush_error {
+            Err(io::Error::new(io::ErrorKind::Other, "test - always_flush_error"))
+        } else {
+            self.flushed = true;
+            Ok(())
+        }
+    }
+}
+
+/// Previously the `LineWriter` could successfully write some bytes but
+/// then fail to report that it has done so. Additionally, an erroneous
+/// flush after a successful write was permanently ignored.
+///
+/// Test that a line writer correctly reports the number of written bytes,
+/// and that it attempts to flush buffered lines from previous writes
+/// before processing new data
+///
+/// Regression test for #37807
+#[test]
+fn erroneous_flush_retried() {
+    let writer = ProgrammableSink {
+        // Only write up to 4 bytes at a time
+        accept_prefix: Some(4),
+
+        // Accept the first two writes, then error the others
+        max_writes: Some(2),
+        error_after_max_writes: true,
+
+        ..Default::default()
+    };
+
+    // This should write the first 4 bytes. The rest will be buffered, out
+    // to the last newline.
+    let mut writer = LineWriter::new(writer);
+    assert_eq!(writer.write(b"a\nb\nc\nd\ne").unwrap(), 8);
+
+    // This write should attempt to flush "c\nd\n", then buffer "e". No
+    // errors should happen here because no further writes should be
+    // attempted against `writer`.
+    assert_eq!(writer.write(b"e").unwrap(), 1);
+    assert_eq!(&writer.get_ref().buffer, b"a\nb\nc\nd\n");
+}
+
+#[test]
+fn line_vectored() {
+    let mut a = LineWriter::new(Vec::new());
+    assert_eq!(
+        a.write_vectored(&[
+            IoSlice::new(&[]),
+            IoSlice::new(b"\n"),
+            IoSlice::new(&[]),
+            IoSlice::new(b"a"),
+        ])
+        .unwrap(),
+        2,
+    );
+    assert_eq!(a.get_ref(), b"\n");
+
+    assert_eq!(
+        a.write_vectored(&[
+            IoSlice::new(&[]),
+            IoSlice::new(b"b"),
+            IoSlice::new(&[]),
+            IoSlice::new(b"a"),
+            IoSlice::new(&[]),
+            IoSlice::new(b"c"),
+        ])
+        .unwrap(),
+        3,
+    );
+    assert_eq!(a.get_ref(), b"\n");
+    a.flush().unwrap();
+    assert_eq!(a.get_ref(), b"\nabac");
+    assert_eq!(a.write_vectored(&[]).unwrap(), 0);
+    assert_eq!(
+        a.write_vectored(&[
+            IoSlice::new(&[]),
+            IoSlice::new(&[]),
+            IoSlice::new(&[]),
+            IoSlice::new(&[]),
+        ])
+        .unwrap(),
+        0,
+    );
+    assert_eq!(a.write_vectored(&[IoSlice::new(b"a\nb"),]).unwrap(), 3);
+    assert_eq!(a.get_ref(), b"\nabaca\nb");
+}
+
+#[test]
+fn line_vectored_partial_and_errors() {
+    use crate::collections::VecDeque;
+
+    enum Call {
+        Write { inputs: Vec<&'static [u8]>, output: io::Result<usize> },
+        Flush { output: io::Result<()> },
+    }
+
+    #[derive(Default)]
+    struct Writer {
+        calls: VecDeque<Call>,
+    }
+
+    impl Write for Writer {
+        fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+            self.write_vectored(&[IoSlice::new(buf)])
+        }
+
+        fn write_vectored(&mut self, buf: &[IoSlice<'_>]) -> io::Result<usize> {
+            match self.calls.pop_front().expect("unexpected call to write") {
+                Call::Write { inputs, output } => {
+                    assert_eq!(inputs, buf.iter().map(|b| &**b).collect::<Vec<_>>());
+                    output
+                }
+                Call::Flush { .. } => panic!("unexpected call to write; expected a flush"),
+            }
+        }
+
+        fn is_write_vectored(&self) -> bool {
+            true
+        }
+
+        fn flush(&mut self) -> io::Result<()> {
+            match self.calls.pop_front().expect("Unexpected call to flush") {
+                Call::Flush { output } => output,
+                Call::Write { .. } => panic!("unexpected call to flush; expected a write"),
+            }
+        }
+    }
+
+    impl Drop for Writer {
+        fn drop(&mut self) {
+            if !thread::panicking() {
+                assert_eq!(self.calls.len(), 0);
+            }
+        }
+    }
+
+    // partial writes keep going
+    let mut a = LineWriter::new(Writer::default());
+    a.write_vectored(&[IoSlice::new(&[]), IoSlice::new(b"abc")]).unwrap();
+
+    a.get_mut().calls.push_back(Call::Write { inputs: vec![b"abc"], output: Ok(1) });
+    a.get_mut().calls.push_back(Call::Write { inputs: vec![b"bc"], output: Ok(2) });
+    a.get_mut().calls.push_back(Call::Write { inputs: vec![b"x", b"\n"], output: Ok(2) });
+
+    a.write_vectored(&[IoSlice::new(b"x"), IoSlice::new(b"\n")]).unwrap();
+
+    a.get_mut().calls.push_back(Call::Flush { output: Ok(()) });
+    a.flush().unwrap();
+
+    // erroneous writes stop and don't write more
+    a.get_mut().calls.push_back(Call::Write { inputs: vec![b"x", b"\na"], output: Err(err()) });
+    a.get_mut().calls.push_back(Call::Flush { output: Ok(()) });
+    assert!(a.write_vectored(&[IoSlice::new(b"x"), IoSlice::new(b"\na")]).is_err());
+    a.flush().unwrap();
+
+    fn err() -> io::Error {
+        io::Error::new(io::ErrorKind::Other, "x")
+    }
+}
+
+/// Test that, in cases where vectored writing is not enabled, the
+/// LineWriter uses the normal `write` call, which more-correctly handles
+/// partial lines
+#[test]
+fn line_vectored_ignored() {
+    let writer = ProgrammableSink::default();
+    let mut writer = LineWriter::new(writer);
+
+    let content = [
+        IoSlice::new(&[]),
+        IoSlice::new(b"Line 1\nLine"),
+        IoSlice::new(b" 2\nLine 3\nL"),
+        IoSlice::new(&[]),
+        IoSlice::new(&[]),
+        IoSlice::new(b"ine 4"),
+        IoSlice::new(b"\nLine 5\n"),
+    ];
+
+    let count = writer.write_vectored(&content).unwrap();
+    assert_eq!(count, 11);
+    assert_eq!(&writer.get_ref().buffer, b"Line 1\n");
+
+    let count = writer.write_vectored(&content[2..]).unwrap();
+    assert_eq!(count, 11);
+    assert_eq!(&writer.get_ref().buffer, b"Line 1\nLine 2\nLine 3\n");
+
+    let count = writer.write_vectored(&content[5..]).unwrap();
+    assert_eq!(count, 5);
+    assert_eq!(&writer.get_ref().buffer, b"Line 1\nLine 2\nLine 3\n");
+
+    let count = writer.write_vectored(&content[6..]).unwrap();
+    assert_eq!(count, 8);
+    assert_eq!(
+        writer.get_ref().buffer.as_slice(),
+        b"Line 1\nLine 2\nLine 3\nLine 4\nLine 5\n".as_ref()
+    );
+}
+
+/// Test that, given this input:
+///
+/// Line 1\n
+/// Line 2\n
+/// Line 3\n
+/// Line 4
+///
+/// And given a result that only writes to midway through Line 2
+///
+/// That only up to the end of Line 3 is buffered
+///
+/// This behavior is desirable because it prevents flushing partial lines
+#[test]
+fn partial_write_buffers_line() {
+    let writer = ProgrammableSink { accept_prefix: Some(13), ..Default::default() };
+    let mut writer = LineWriter::new(writer);
+
+    assert_eq!(writer.write(b"Line 1\nLine 2\nLine 3\nLine4").unwrap(), 21);
+    assert_eq!(&writer.get_ref().buffer, b"Line 1\nLine 2");
+
+    assert_eq!(writer.write(b"Line 4").unwrap(), 6);
+    assert_eq!(&writer.get_ref().buffer, b"Line 1\nLine 2\nLine 3\n");
+}
+
+/// Test that, given this input:
+///
+/// Line 1\n
+/// Line 2\n
+/// Line 3
+///
+/// And given that the full write of lines 1 and 2 was successful
+/// That data up to Line 3 is buffered
+#[test]
+fn partial_line_buffered_after_line_write() {
+    let writer = ProgrammableSink::default();
+    let mut writer = LineWriter::new(writer);
+
+    assert_eq!(writer.write(b"Line 1\nLine 2\nLine 3").unwrap(), 20);
+    assert_eq!(&writer.get_ref().buffer, b"Line 1\nLine 2\n");
+
+    assert!(writer.flush().is_ok());
+    assert_eq!(&writer.get_ref().buffer, b"Line 1\nLine 2\nLine 3");
+}
+
+/// Test that, given a partial line that exceeds the length of
+/// LineBuffer's buffer (that is, without a trailing newline), that that
+/// line is written to the inner writer
+#[test]
+fn long_line_flushed() {
+    let writer = ProgrammableSink::default();
+    let mut writer = LineWriter::with_capacity(5, writer);
+
+    assert_eq!(writer.write(b"0123456789").unwrap(), 10);
+    assert_eq!(&writer.get_ref().buffer, b"0123456789");
+}
+
+/// Test that, given a very long partial line *after* successfully
+/// flushing a complete line, that that line is buffered unconditionally,
+/// and no additional writes take place. This assures the property that
+/// `write` should make at-most-one attempt to write new data.
+#[test]
+fn line_long_tail_not_flushed() {
+    let writer = ProgrammableSink::default();
+    let mut writer = LineWriter::with_capacity(5, writer);
+
+    // Assert that Line 1\n is flushed, and 01234 is buffered
+    assert_eq!(writer.write(b"Line 1\n0123456789").unwrap(), 12);
+    assert_eq!(&writer.get_ref().buffer, b"Line 1\n");
+
+    // Because the buffer is full, this subsequent write will flush it
+    assert_eq!(writer.write(b"5").unwrap(), 1);
+    assert_eq!(&writer.get_ref().buffer, b"Line 1\n01234");
+}
+
+/// Test that, if an attempt to pre-flush buffered data returns Ok(0),
+/// this is propagated as an error.
+#[test]
+fn line_buffer_write0_error() {
+    let writer = ProgrammableSink {
+        // Accept one write, then return Ok(0) on subsequent ones
+        max_writes: Some(1),
+
+        ..Default::default()
+    };
+    let mut writer = LineWriter::new(writer);
+
+    // This should write "Line 1\n" and buffer "Partial"
+    assert_eq!(writer.write(b"Line 1\nPartial").unwrap(), 14);
+    assert_eq!(&writer.get_ref().buffer, b"Line 1\n");
+
+    // This will attempt to flush "partial", which will return Ok(0), which
+    // needs to be an error, because we've already informed the client
+    // that we accepted the write.
+    let err = writer.write(b" Line End\n").unwrap_err();
+    assert_eq!(err.kind(), ErrorKind::WriteZero);
+    assert_eq!(&writer.get_ref().buffer, b"Line 1\n");
+}
+
+/// Test that, if a write returns Ok(0) after a successful pre-flush, this
+/// is propagated as Ok(0)
+#[test]
+fn line_buffer_write0_normal() {
+    let writer = ProgrammableSink {
+        // Accept two writes, then return Ok(0) on subsequent ones
+        max_writes: Some(2),
+
+        ..Default::default()
+    };
+    let mut writer = LineWriter::new(writer);
+
+    // This should write "Line 1\n" and buffer "Partial"
+    assert_eq!(writer.write(b"Line 1\nPartial").unwrap(), 14);
+    assert_eq!(&writer.get_ref().buffer, b"Line 1\n");
+
+    // This will flush partial, which will succeed, but then return Ok(0)
+    // when flushing " Line End\n"
+    assert_eq!(writer.write(b" Line End\n").unwrap(), 0);
+    assert_eq!(&writer.get_ref().buffer, b"Line 1\nPartial");
+}
+
+/// LineWriter has a custom `write_all`; make sure it works correctly
+#[test]
+fn line_write_all() {
+    let writer = ProgrammableSink {
+        // Only write 5 bytes at a time
+        accept_prefix: Some(5),
+        ..Default::default()
+    };
+    let mut writer = LineWriter::new(writer);
+
+    writer.write_all(b"Line 1\nLine 2\nLine 3\nLine 4\nPartial").unwrap();
+    assert_eq!(&writer.get_ref().buffer, b"Line 1\nLine 2\nLine 3\nLine 4\n");
+    writer.write_all(b" Line 5\n").unwrap();
+    assert_eq!(
+        writer.get_ref().buffer.as_slice(),
+        b"Line 1\nLine 2\nLine 3\nLine 4\nPartial Line 5\n".as_ref(),
+    );
+}
+
+#[test]
+fn line_write_all_error() {
+    let writer = ProgrammableSink {
+        // Only accept up to 3 writes of up to 5 bytes each
+        accept_prefix: Some(5),
+        max_writes: Some(3),
+        ..Default::default()
+    };
+
+    let mut writer = LineWriter::new(writer);
+    let res = writer.write_all(b"Line 1\nLine 2\nLine 3\nLine 4\nPartial");
+    assert!(res.is_err());
+    // An error from write_all leaves everything in an indeterminate state,
+    // so there's nothing else to test here
+}
+
+/// Under certain circumstances, the old implementation of LineWriter
+/// would try to buffer "to the last newline" but be forced to buffer
+/// less than that, leading to inappropriate partial line writes.
+/// Regression test for that issue.
+#[test]
+fn partial_multiline_buffering() {
+    let writer = ProgrammableSink {
+        // Write only up to 5 bytes at a time
+        accept_prefix: Some(5),
+        ..Default::default()
+    };
+
+    let mut writer = LineWriter::with_capacity(10, writer);
+
+    let content = b"AAAAABBBBB\nCCCCDDDDDD\nEEE";
+
+    // When content is written, LineWriter will try to write blocks A, B,
+    // C, and D. Only block A will succeed. Under the old behavior, LineWriter
+    // would then try to buffer B, C and D, but because its capacity is 10,
+    // it will only be able to buffer B and C. We don't want to buffer
+    // partial lines concurrent with whole lines, so the correct behavior
+    // is to buffer only block B (out to the newline)
+    assert_eq!(writer.write(content).unwrap(), 11);
+    assert_eq!(writer.get_ref().buffer, *b"AAAAA");
+
+    writer.flush().unwrap();
+    assert_eq!(writer.get_ref().buffer, *b"AAAAABBBBB\n");
+}
+
+/// Same as test_partial_multiline_buffering, but in the event NO full lines
+/// fit in the buffer, just buffer as much as possible
+#[test]
+fn partial_multiline_buffering_without_full_line() {
+    let writer = ProgrammableSink {
+        // Write only up to 5 bytes at a time
+        accept_prefix: Some(5),
+        ..Default::default()
+    };
+
+    let mut writer = LineWriter::with_capacity(5, writer);
+
+    let content = b"AAAAABBBBBBBBBB\nCCCCC\nDDDDD";
+
+    // When content is written, LineWriter will try to write blocks A, B,
+    // and C. Only block A will succeed. Under the old behavior, LineWriter
+    // would then try to buffer B and C, but because its capacity is 5,
+    // it will only be able to buffer part of B. Because it's not possible
+    // for it to buffer any complete lines, it should buffer as much of B as
+    // possible
+    assert_eq!(writer.write(content).unwrap(), 10);
+    assert_eq!(writer.get_ref().buffer, *b"AAAAA");
+
+    writer.flush().unwrap();
+    assert_eq!(writer.get_ref().buffer, *b"AAAAABBBBB");
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+enum RecordedEvent {
+    Write(String),
+    Flush,
+}
+
+#[derive(Debug, Clone, Default)]
+struct WriteRecorder {
+    pub events: Vec<RecordedEvent>,
+}
+
+impl Write for WriteRecorder {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        use crate::str::from_utf8;
+
+        self.events.push(RecordedEvent::Write(from_utf8(buf).unwrap().to_string()));
+        Ok(buf.len())
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        self.events.push(RecordedEvent::Flush);
+        Ok(())
+    }
+}
+
+/// Test that a normal, formatted writeln only results in a single write
+/// call to the underlying writer. A naive implementation of
+/// LineWriter::write_all results in two writes: one of the buffered data,
+/// and another of the final substring in the formatted set
+#[test]
+fn single_formatted_write() {
+    let writer = WriteRecorder::default();
+    let mut writer = LineWriter::new(writer);
+
+    // Under a naive implementation of LineWriter, this will result in two
+    // writes: "hello, world" and "!\n", because write() has to flush the
+    // buffer before attempting to write the last "!\n". write_all shouldn't
+    // have this limitation.
+    writeln!(&mut writer, "{}, {}!", "hello", "world").unwrap();
+    assert_eq!(writer.get_ref().events, [RecordedEvent::Write("hello, world!\n".to_string())]);
+}
diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs
index 58343f66f3f..5733735dc4a 100644
--- a/library/std/src/io/cursor.rs
+++ b/library/std/src/io/cursor.rs
@@ -1,3 +1,6 @@
+#[cfg(test)]
+mod tests;
+
 use crate::io::prelude::*;
 
 use crate::cmp;
@@ -447,531 +450,3 @@ impl Write for Cursor<Box<[u8]>> {
         Ok(())
     }
 }
-
-#[cfg(test)]
-mod tests {
-    use crate::io::prelude::*;
-    use crate::io::{Cursor, IoSlice, IoSliceMut, SeekFrom};
-
-    #[test]
-    fn test_vec_writer() {
-        let mut writer = Vec::new();
-        assert_eq!(writer.write(&[0]).unwrap(), 1);
-        assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
-        assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
-        assert_eq!(
-            writer
-                .write_vectored(&[IoSlice::new(&[]), IoSlice::new(&[8, 9]), IoSlice::new(&[10])],)
-                .unwrap(),
-            3
-        );
-        let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
-        assert_eq!(writer, b);
-    }
-
-    #[test]
-    fn test_mem_writer() {
-        let mut writer = Cursor::new(Vec::new());
-        assert_eq!(writer.write(&[0]).unwrap(), 1);
-        assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
-        assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
-        assert_eq!(
-            writer
-                .write_vectored(&[IoSlice::new(&[]), IoSlice::new(&[8, 9]), IoSlice::new(&[10])],)
-                .unwrap(),
-            3
-        );
-        let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
-        assert_eq!(&writer.get_ref()[..], b);
-    }
-
-    #[test]
-    fn test_mem_mut_writer() {
-        let mut vec = Vec::new();
-        let mut writer = Cursor::new(&mut vec);
-        assert_eq!(writer.write(&[0]).unwrap(), 1);
-        assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
-        assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
-        assert_eq!(
-            writer
-                .write_vectored(&[IoSlice::new(&[]), IoSlice::new(&[8, 9]), IoSlice::new(&[10])],)
-                .unwrap(),
-            3
-        );
-        let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
-        assert_eq!(&writer.get_ref()[..], b);
-    }
-
-    #[test]
-    fn test_box_slice_writer() {
-        let mut writer = Cursor::new(vec![0u8; 9].into_boxed_slice());
-        assert_eq!(writer.position(), 0);
-        assert_eq!(writer.write(&[0]).unwrap(), 1);
-        assert_eq!(writer.position(), 1);
-        assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
-        assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
-        assert_eq!(writer.position(), 8);
-        assert_eq!(writer.write(&[]).unwrap(), 0);
-        assert_eq!(writer.position(), 8);
-
-        assert_eq!(writer.write(&[8, 9]).unwrap(), 1);
-        assert_eq!(writer.write(&[10]).unwrap(), 0);
-        let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8];
-        assert_eq!(&**writer.get_ref(), b);
-    }
-
-    #[test]
-    fn test_box_slice_writer_vectored() {
-        let mut writer = Cursor::new(vec![0u8; 9].into_boxed_slice());
-        assert_eq!(writer.position(), 0);
-        assert_eq!(writer.write_vectored(&[IoSlice::new(&[0])]).unwrap(), 1);
-        assert_eq!(writer.position(), 1);
-        assert_eq!(
-            writer
-                .write_vectored(&[IoSlice::new(&[1, 2, 3]), IoSlice::new(&[4, 5, 6, 7]),])
-                .unwrap(),
-            7,
-        );
-        assert_eq!(writer.position(), 8);
-        assert_eq!(writer.write_vectored(&[]).unwrap(), 0);
-        assert_eq!(writer.position(), 8);
-
-        assert_eq!(writer.write_vectored(&[IoSlice::new(&[8, 9])]).unwrap(), 1);
-        assert_eq!(writer.write_vectored(&[IoSlice::new(&[10])]).unwrap(), 0);
-        let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8];
-        assert_eq!(&**writer.get_ref(), b);
-    }
-
-    #[test]
-    fn test_buf_writer() {
-        let mut buf = [0 as u8; 9];
-        {
-            let mut writer = Cursor::new(&mut buf[..]);
-            assert_eq!(writer.position(), 0);
-            assert_eq!(writer.write(&[0]).unwrap(), 1);
-            assert_eq!(writer.position(), 1);
-            assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
-            assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
-            assert_eq!(writer.position(), 8);
-            assert_eq!(writer.write(&[]).unwrap(), 0);
-            assert_eq!(writer.position(), 8);
-
-            assert_eq!(writer.write(&[8, 9]).unwrap(), 1);
-            assert_eq!(writer.write(&[10]).unwrap(), 0);
-        }
-        let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8];
-        assert_eq!(buf, b);
-    }
-
-    #[test]
-    fn test_buf_writer_vectored() {
-        let mut buf = [0 as u8; 9];
-        {
-            let mut writer = Cursor::new(&mut buf[..]);
-            assert_eq!(writer.position(), 0);
-            assert_eq!(writer.write_vectored(&[IoSlice::new(&[0])]).unwrap(), 1);
-            assert_eq!(writer.position(), 1);
-            assert_eq!(
-                writer
-                    .write_vectored(&[IoSlice::new(&[1, 2, 3]), IoSlice::new(&[4, 5, 6, 7])],)
-                    .unwrap(),
-                7,
-            );
-            assert_eq!(writer.position(), 8);
-            assert_eq!(writer.write_vectored(&[]).unwrap(), 0);
-            assert_eq!(writer.position(), 8);
-
-            assert_eq!(writer.write_vectored(&[IoSlice::new(&[8, 9])]).unwrap(), 1);
-            assert_eq!(writer.write_vectored(&[IoSlice::new(&[10])]).unwrap(), 0);
-        }
-        let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8];
-        assert_eq!(buf, b);
-    }
-
-    #[test]
-    fn test_buf_writer_seek() {
-        let mut buf = [0 as u8; 8];
-        {
-            let mut writer = Cursor::new(&mut buf[..]);
-            assert_eq!(writer.position(), 0);
-            assert_eq!(writer.write(&[1]).unwrap(), 1);
-            assert_eq!(writer.position(), 1);
-
-            assert_eq!(writer.seek(SeekFrom::Start(2)).unwrap(), 2);
-            assert_eq!(writer.position(), 2);
-            assert_eq!(writer.write(&[2]).unwrap(), 1);
-            assert_eq!(writer.position(), 3);
-
-            assert_eq!(writer.seek(SeekFrom::Current(-2)).unwrap(), 1);
-            assert_eq!(writer.position(), 1);
-            assert_eq!(writer.write(&[3]).unwrap(), 1);
-            assert_eq!(writer.position(), 2);
-
-            assert_eq!(writer.seek(SeekFrom::End(-1)).unwrap(), 7);
-            assert_eq!(writer.position(), 7);
-            assert_eq!(writer.write(&[4]).unwrap(), 1);
-            assert_eq!(writer.position(), 8);
-        }
-        let b: &[_] = &[1, 3, 2, 0, 0, 0, 0, 4];
-        assert_eq!(buf, b);
-    }
-
-    #[test]
-    fn test_buf_writer_error() {
-        let mut buf = [0 as u8; 2];
-        let mut writer = Cursor::new(&mut buf[..]);
-        assert_eq!(writer.write(&[0]).unwrap(), 1);
-        assert_eq!(writer.write(&[0, 0]).unwrap(), 1);
-        assert_eq!(writer.write(&[0, 0]).unwrap(), 0);
-    }
-
-    #[test]
-    fn test_mem_reader() {
-        let mut reader = Cursor::new(vec![0, 1, 2, 3, 4, 5, 6, 7]);
-        let mut buf = [];
-        assert_eq!(reader.read(&mut buf).unwrap(), 0);
-        assert_eq!(reader.position(), 0);
-        let mut buf = [0];
-        assert_eq!(reader.read(&mut buf).unwrap(), 1);
-        assert_eq!(reader.position(), 1);
-        let b: &[_] = &[0];
-        assert_eq!(buf, b);
-        let mut buf = [0; 4];
-        assert_eq!(reader.read(&mut buf).unwrap(), 4);
-        assert_eq!(reader.position(), 5);
-        let b: &[_] = &[1, 2, 3, 4];
-        assert_eq!(buf, b);
-        assert_eq!(reader.read(&mut buf).unwrap(), 3);
-        let b: &[_] = &[5, 6, 7];
-        assert_eq!(&buf[..3], b);
-        assert_eq!(reader.read(&mut buf).unwrap(), 0);
-    }
-
-    #[test]
-    fn test_mem_reader_vectored() {
-        let mut reader = Cursor::new(vec![0, 1, 2, 3, 4, 5, 6, 7]);
-        let mut buf = [];
-        assert_eq!(reader.read_vectored(&mut [IoSliceMut::new(&mut buf)]).unwrap(), 0);
-        assert_eq!(reader.position(), 0);
-        let mut buf = [0];
-        assert_eq!(
-            reader
-                .read_vectored(&mut [IoSliceMut::new(&mut []), IoSliceMut::new(&mut buf),])
-                .unwrap(),
-            1,
-        );
-        assert_eq!(reader.position(), 1);
-        let b: &[_] = &[0];
-        assert_eq!(buf, b);
-        let mut buf1 = [0; 4];
-        let mut buf2 = [0; 4];
-        assert_eq!(
-            reader
-                .read_vectored(&mut [IoSliceMut::new(&mut buf1), IoSliceMut::new(&mut buf2),])
-                .unwrap(),
-            7,
-        );
-        let b1: &[_] = &[1, 2, 3, 4];
-        let b2: &[_] = &[5, 6, 7];
-        assert_eq!(buf1, b1);
-        assert_eq!(&buf2[..3], b2);
-        assert_eq!(reader.read(&mut buf).unwrap(), 0);
-    }
-
-    #[test]
-    fn test_boxed_slice_reader() {
-        let mut reader = Cursor::new(vec![0, 1, 2, 3, 4, 5, 6, 7].into_boxed_slice());
-        let mut buf = [];
-        assert_eq!(reader.read(&mut buf).unwrap(), 0);
-        assert_eq!(reader.position(), 0);
-        let mut buf = [0];
-        assert_eq!(reader.read(&mut buf).unwrap(), 1);
-        assert_eq!(reader.position(), 1);
-        let b: &[_] = &[0];
-        assert_eq!(buf, b);
-        let mut buf = [0; 4];
-        assert_eq!(reader.read(&mut buf).unwrap(), 4);
-        assert_eq!(reader.position(), 5);
-        let b: &[_] = &[1, 2, 3, 4];
-        assert_eq!(buf, b);
-        assert_eq!(reader.read(&mut buf).unwrap(), 3);
-        let b: &[_] = &[5, 6, 7];
-        assert_eq!(&buf[..3], b);
-        assert_eq!(reader.read(&mut buf).unwrap(), 0);
-    }
-
-    #[test]
-    fn test_boxed_slice_reader_vectored() {
-        let mut reader = Cursor::new(vec![0, 1, 2, 3, 4, 5, 6, 7].into_boxed_slice());
-        let mut buf = [];
-        assert_eq!(reader.read_vectored(&mut [IoSliceMut::new(&mut buf)]).unwrap(), 0);
-        assert_eq!(reader.position(), 0);
-        let mut buf = [0];
-        assert_eq!(
-            reader
-                .read_vectored(&mut [IoSliceMut::new(&mut []), IoSliceMut::new(&mut buf),])
-                .unwrap(),
-            1,
-        );
-        assert_eq!(reader.position(), 1);
-        let b: &[_] = &[0];
-        assert_eq!(buf, b);
-        let mut buf1 = [0; 4];
-        let mut buf2 = [0; 4];
-        assert_eq!(
-            reader
-                .read_vectored(&mut [IoSliceMut::new(&mut buf1), IoSliceMut::new(&mut buf2)],)
-                .unwrap(),
-            7,
-        );
-        let b1: &[_] = &[1, 2, 3, 4];
-        let b2: &[_] = &[5, 6, 7];
-        assert_eq!(buf1, b1);
-        assert_eq!(&buf2[..3], b2);
-        assert_eq!(reader.read(&mut buf).unwrap(), 0);
-    }
-
-    #[test]
-    fn read_to_end() {
-        let mut reader = Cursor::new(vec![0, 1, 2, 3, 4, 5, 6, 7]);
-        let mut v = Vec::new();
-        reader.read_to_end(&mut v).unwrap();
-        assert_eq!(v, [0, 1, 2, 3, 4, 5, 6, 7]);
-    }
-
-    #[test]
-    fn test_slice_reader() {
-        let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
-        let reader = &mut &in_buf[..];
-        let mut buf = [];
-        assert_eq!(reader.read(&mut buf).unwrap(), 0);
-        let mut buf = [0];
-        assert_eq!(reader.read(&mut buf).unwrap(), 1);
-        assert_eq!(reader.len(), 7);
-        let b: &[_] = &[0];
-        assert_eq!(&buf[..], b);
-        let mut buf = [0; 4];
-        assert_eq!(reader.read(&mut buf).unwrap(), 4);
-        assert_eq!(reader.len(), 3);
-        let b: &[_] = &[1, 2, 3, 4];
-        assert_eq!(&buf[..], b);
-        assert_eq!(reader.read(&mut buf).unwrap(), 3);
-        let b: &[_] = &[5, 6, 7];
-        assert_eq!(&buf[..3], b);
-        assert_eq!(reader.read(&mut buf).unwrap(), 0);
-    }
-
-    #[test]
-    fn test_slice_reader_vectored() {
-        let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
-        let reader = &mut &in_buf[..];
-        let mut buf = [];
-        assert_eq!(reader.read_vectored(&mut [IoSliceMut::new(&mut buf)]).unwrap(), 0);
-        let mut buf = [0];
-        assert_eq!(
-            reader
-                .read_vectored(&mut [IoSliceMut::new(&mut []), IoSliceMut::new(&mut buf),])
-                .unwrap(),
-            1,
-        );
-        assert_eq!(reader.len(), 7);
-        let b: &[_] = &[0];
-        assert_eq!(buf, b);
-        let mut buf1 = [0; 4];
-        let mut buf2 = [0; 4];
-        assert_eq!(
-            reader
-                .read_vectored(&mut [IoSliceMut::new(&mut buf1), IoSliceMut::new(&mut buf2)],)
-                .unwrap(),
-            7,
-        );
-        let b1: &[_] = &[1, 2, 3, 4];
-        let b2: &[_] = &[5, 6, 7];
-        assert_eq!(buf1, b1);
-        assert_eq!(&buf2[..3], b2);
-        assert_eq!(reader.read(&mut buf).unwrap(), 0);
-    }
-
-    #[test]
-    fn test_read_exact() {
-        let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
-        let reader = &mut &in_buf[..];
-        let mut buf = [];
-        assert!(reader.read_exact(&mut buf).is_ok());
-        let mut buf = [8];
-        assert!(reader.read_exact(&mut buf).is_ok());
-        assert_eq!(buf[0], 0);
-        assert_eq!(reader.len(), 7);
-        let mut buf = [0, 0, 0, 0, 0, 0, 0];
-        assert!(reader.read_exact(&mut buf).is_ok());
-        assert_eq!(buf, [1, 2, 3, 4, 5, 6, 7]);
-        assert_eq!(reader.len(), 0);
-        let mut buf = [0];
-        assert!(reader.read_exact(&mut buf).is_err());
-    }
-
-    #[test]
-    fn test_buf_reader() {
-        let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
-        let mut reader = Cursor::new(&in_buf[..]);
-        let mut buf = [];
-        assert_eq!(reader.read(&mut buf).unwrap(), 0);
-        assert_eq!(reader.position(), 0);
-        let mut buf = [0];
-        assert_eq!(reader.read(&mut buf).unwrap(), 1);
-        assert_eq!(reader.position(), 1);
-        let b: &[_] = &[0];
-        assert_eq!(buf, b);
-        let mut buf = [0; 4];
-        assert_eq!(reader.read(&mut buf).unwrap(), 4);
-        assert_eq!(reader.position(), 5);
-        let b: &[_] = &[1, 2, 3, 4];
-        assert_eq!(buf, b);
-        assert_eq!(reader.read(&mut buf).unwrap(), 3);
-        let b: &[_] = &[5, 6, 7];
-        assert_eq!(&buf[..3], b);
-        assert_eq!(reader.read(&mut buf).unwrap(), 0);
-    }
-
-    #[test]
-    fn seek_past_end() {
-        let buf = [0xff];
-        let mut r = Cursor::new(&buf[..]);
-        assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10);
-        assert_eq!(r.read(&mut [0]).unwrap(), 0);
-
-        let mut r = Cursor::new(vec![10]);
-        assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10);
-        assert_eq!(r.read(&mut [0]).unwrap(), 0);
-
-        let mut buf = [0];
-        let mut r = Cursor::new(&mut buf[..]);
-        assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10);
-        assert_eq!(r.write(&[3]).unwrap(), 0);
-
-        let mut r = Cursor::new(vec![10].into_boxed_slice());
-        assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10);
-        assert_eq!(r.write(&[3]).unwrap(), 0);
-    }
-
-    #[test]
-    fn seek_past_i64() {
-        let buf = [0xff];
-        let mut r = Cursor::new(&buf[..]);
-        assert_eq!(r.seek(SeekFrom::Start(6)).unwrap(), 6);
-        assert_eq!(r.seek(SeekFrom::Current(0x7ffffffffffffff0)).unwrap(), 0x7ffffffffffffff6);
-        assert_eq!(r.seek(SeekFrom::Current(0x10)).unwrap(), 0x8000000000000006);
-        assert_eq!(r.seek(SeekFrom::Current(0)).unwrap(), 0x8000000000000006);
-        assert!(r.seek(SeekFrom::Current(0x7ffffffffffffffd)).is_err());
-        assert_eq!(r.seek(SeekFrom::Current(-0x8000000000000000)).unwrap(), 6);
-
-        let mut r = Cursor::new(vec![10]);
-        assert_eq!(r.seek(SeekFrom::Start(6)).unwrap(), 6);
-        assert_eq!(r.seek(SeekFrom::Current(0x7ffffffffffffff0)).unwrap(), 0x7ffffffffffffff6);
-        assert_eq!(r.seek(SeekFrom::Current(0x10)).unwrap(), 0x8000000000000006);
-        assert_eq!(r.seek(SeekFrom::Current(0)).unwrap(), 0x8000000000000006);
-        assert!(r.seek(SeekFrom::Current(0x7ffffffffffffffd)).is_err());
-        assert_eq!(r.seek(SeekFrom::Current(-0x8000000000000000)).unwrap(), 6);
-
-        let mut buf = [0];
-        let mut r = Cursor::new(&mut buf[..]);
-        assert_eq!(r.seek(SeekFrom::Start(6)).unwrap(), 6);
-        assert_eq!(r.seek(SeekFrom::Current(0x7ffffffffffffff0)).unwrap(), 0x7ffffffffffffff6);
-        assert_eq!(r.seek(SeekFrom::Current(0x10)).unwrap(), 0x8000000000000006);
-        assert_eq!(r.seek(SeekFrom::Current(0)).unwrap(), 0x8000000000000006);
-        assert!(r.seek(SeekFrom::Current(0x7ffffffffffffffd)).is_err());
-        assert_eq!(r.seek(SeekFrom::Current(-0x8000000000000000)).unwrap(), 6);
-
-        let mut r = Cursor::new(vec![10].into_boxed_slice());
-        assert_eq!(r.seek(SeekFrom::Start(6)).unwrap(), 6);
-        assert_eq!(r.seek(SeekFrom::Current(0x7ffffffffffffff0)).unwrap(), 0x7ffffffffffffff6);
-        assert_eq!(r.seek(SeekFrom::Current(0x10)).unwrap(), 0x8000000000000006);
-        assert_eq!(r.seek(SeekFrom::Current(0)).unwrap(), 0x8000000000000006);
-        assert!(r.seek(SeekFrom::Current(0x7ffffffffffffffd)).is_err());
-        assert_eq!(r.seek(SeekFrom::Current(-0x8000000000000000)).unwrap(), 6);
-    }
-
-    #[test]
-    fn seek_before_0() {
-        let buf = [0xff];
-        let mut r = Cursor::new(&buf[..]);
-        assert!(r.seek(SeekFrom::End(-2)).is_err());
-
-        let mut r = Cursor::new(vec![10]);
-        assert!(r.seek(SeekFrom::End(-2)).is_err());
-
-        let mut buf = [0];
-        let mut r = Cursor::new(&mut buf[..]);
-        assert!(r.seek(SeekFrom::End(-2)).is_err());
-
-        let mut r = Cursor::new(vec![10].into_boxed_slice());
-        assert!(r.seek(SeekFrom::End(-2)).is_err());
-    }
-
-    #[test]
-    fn test_seekable_mem_writer() {
-        let mut writer = Cursor::new(Vec::<u8>::new());
-        assert_eq!(writer.position(), 0);
-        assert_eq!(writer.write(&[0]).unwrap(), 1);
-        assert_eq!(writer.position(), 1);
-        assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
-        assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
-        assert_eq!(writer.position(), 8);
-        let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
-        assert_eq!(&writer.get_ref()[..], b);
-
-        assert_eq!(writer.seek(SeekFrom::Start(0)).unwrap(), 0);
-        assert_eq!(writer.position(), 0);
-        assert_eq!(writer.write(&[3, 4]).unwrap(), 2);
-        let b: &[_] = &[3, 4, 2, 3, 4, 5, 6, 7];
-        assert_eq!(&writer.get_ref()[..], b);
-
-        assert_eq!(writer.seek(SeekFrom::Current(1)).unwrap(), 3);
-        assert_eq!(writer.write(&[0, 1]).unwrap(), 2);
-        let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 7];
-        assert_eq!(&writer.get_ref()[..], b);
-
-        assert_eq!(writer.seek(SeekFrom::End(-1)).unwrap(), 7);
-        assert_eq!(writer.write(&[1, 2]).unwrap(), 2);
-        let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2];
-        assert_eq!(&writer.get_ref()[..], b);
-
-        assert_eq!(writer.seek(SeekFrom::End(1)).unwrap(), 10);
-        assert_eq!(writer.write(&[1]).unwrap(), 1);
-        let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1];
-        assert_eq!(&writer.get_ref()[..], b);
-    }
-
-    #[test]
-    fn vec_seek_past_end() {
-        let mut r = Cursor::new(Vec::new());
-        assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10);
-        assert_eq!(r.write(&[3]).unwrap(), 1);
-    }
-
-    #[test]
-    fn vec_seek_before_0() {
-        let mut r = Cursor::new(Vec::new());
-        assert!(r.seek(SeekFrom::End(-2)).is_err());
-    }
-
-    #[test]
-    #[cfg(target_pointer_width = "32")]
-    fn vec_seek_and_write_past_usize_max() {
-        let mut c = Cursor::new(Vec::new());
-        c.set_position(usize::MAX as u64 + 1);
-        assert!(c.write_all(&[1, 2, 3]).is_err());
-    }
-
-    #[test]
-    fn test_partial_eq() {
-        assert_eq!(Cursor::new(Vec::<u8>::new()), Cursor::new(Vec::<u8>::new()));
-    }
-
-    #[test]
-    fn test_eq() {
-        struct AssertEq<T: Eq>(pub T);
-
-        let _: AssertEq<Cursor<Vec<u8>>> = AssertEq(Cursor::new(Vec::new()));
-    }
-}
diff --git a/library/std/src/io/cursor/tests.rs b/library/std/src/io/cursor/tests.rs
new file mode 100644
index 00000000000..80d88ca66f6
--- /dev/null
+++ b/library/std/src/io/cursor/tests.rs
@@ -0,0 +1,516 @@
+use crate::io::prelude::*;
+use crate::io::{Cursor, IoSlice, IoSliceMut, SeekFrom};
+
+#[test]
+fn test_vec_writer() {
+    let mut writer = Vec::new();
+    assert_eq!(writer.write(&[0]).unwrap(), 1);
+    assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
+    assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
+    assert_eq!(
+        writer
+            .write_vectored(&[IoSlice::new(&[]), IoSlice::new(&[8, 9]), IoSlice::new(&[10])],)
+            .unwrap(),
+        3
+    );
+    let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+    assert_eq!(writer, b);
+}
+
+#[test]
+fn test_mem_writer() {
+    let mut writer = Cursor::new(Vec::new());
+    assert_eq!(writer.write(&[0]).unwrap(), 1);
+    assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
+    assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
+    assert_eq!(
+        writer
+            .write_vectored(&[IoSlice::new(&[]), IoSlice::new(&[8, 9]), IoSlice::new(&[10])],)
+            .unwrap(),
+        3
+    );
+    let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+    assert_eq!(&writer.get_ref()[..], b);
+}
+
+#[test]
+fn test_mem_mut_writer() {
+    let mut vec = Vec::new();
+    let mut writer = Cursor::new(&mut vec);
+    assert_eq!(writer.write(&[0]).unwrap(), 1);
+    assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
+    assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
+    assert_eq!(
+        writer
+            .write_vectored(&[IoSlice::new(&[]), IoSlice::new(&[8, 9]), IoSlice::new(&[10])],)
+            .unwrap(),
+        3
+    );
+    let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+    assert_eq!(&writer.get_ref()[..], b);
+}
+
+#[test]
+fn test_box_slice_writer() {
+    let mut writer = Cursor::new(vec![0u8; 9].into_boxed_slice());
+    assert_eq!(writer.position(), 0);
+    assert_eq!(writer.write(&[0]).unwrap(), 1);
+    assert_eq!(writer.position(), 1);
+    assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
+    assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
+    assert_eq!(writer.position(), 8);
+    assert_eq!(writer.write(&[]).unwrap(), 0);
+    assert_eq!(writer.position(), 8);
+
+    assert_eq!(writer.write(&[8, 9]).unwrap(), 1);
+    assert_eq!(writer.write(&[10]).unwrap(), 0);
+    let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8];
+    assert_eq!(&**writer.get_ref(), b);
+}
+
+#[test]
+fn test_box_slice_writer_vectored() {
+    let mut writer = Cursor::new(vec![0u8; 9].into_boxed_slice());
+    assert_eq!(writer.position(), 0);
+    assert_eq!(writer.write_vectored(&[IoSlice::new(&[0])]).unwrap(), 1);
+    assert_eq!(writer.position(), 1);
+    assert_eq!(
+        writer.write_vectored(&[IoSlice::new(&[1, 2, 3]), IoSlice::new(&[4, 5, 6, 7]),]).unwrap(),
+        7,
+    );
+    assert_eq!(writer.position(), 8);
+    assert_eq!(writer.write_vectored(&[]).unwrap(), 0);
+    assert_eq!(writer.position(), 8);
+
+    assert_eq!(writer.write_vectored(&[IoSlice::new(&[8, 9])]).unwrap(), 1);
+    assert_eq!(writer.write_vectored(&[IoSlice::new(&[10])]).unwrap(), 0);
+    let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8];
+    assert_eq!(&**writer.get_ref(), b);
+}
+
+#[test]
+fn test_buf_writer() {
+    let mut buf = [0 as u8; 9];
+    {
+        let mut writer = Cursor::new(&mut buf[..]);
+        assert_eq!(writer.position(), 0);
+        assert_eq!(writer.write(&[0]).unwrap(), 1);
+        assert_eq!(writer.position(), 1);
+        assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
+        assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
+        assert_eq!(writer.position(), 8);
+        assert_eq!(writer.write(&[]).unwrap(), 0);
+        assert_eq!(writer.position(), 8);
+
+        assert_eq!(writer.write(&[8, 9]).unwrap(), 1);
+        assert_eq!(writer.write(&[10]).unwrap(), 0);
+    }
+    let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8];
+    assert_eq!(buf, b);
+}
+
+#[test]
+fn test_buf_writer_vectored() {
+    let mut buf = [0 as u8; 9];
+    {
+        let mut writer = Cursor::new(&mut buf[..]);
+        assert_eq!(writer.position(), 0);
+        assert_eq!(writer.write_vectored(&[IoSlice::new(&[0])]).unwrap(), 1);
+        assert_eq!(writer.position(), 1);
+        assert_eq!(
+            writer
+                .write_vectored(&[IoSlice::new(&[1, 2, 3]), IoSlice::new(&[4, 5, 6, 7])],)
+                .unwrap(),
+            7,
+        );
+        assert_eq!(writer.position(), 8);
+        assert_eq!(writer.write_vectored(&[]).unwrap(), 0);
+        assert_eq!(writer.position(), 8);
+
+        assert_eq!(writer.write_vectored(&[IoSlice::new(&[8, 9])]).unwrap(), 1);
+        assert_eq!(writer.write_vectored(&[IoSlice::new(&[10])]).unwrap(), 0);
+    }
+    let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8];
+    assert_eq!(buf, b);
+}
+
+#[test]
+fn test_buf_writer_seek() {
+    let mut buf = [0 as u8; 8];
+    {
+        let mut writer = Cursor::new(&mut buf[..]);
+        assert_eq!(writer.position(), 0);
+        assert_eq!(writer.write(&[1]).unwrap(), 1);
+        assert_eq!(writer.position(), 1);
+
+        assert_eq!(writer.seek(SeekFrom::Start(2)).unwrap(), 2);
+        assert_eq!(writer.position(), 2);
+        assert_eq!(writer.write(&[2]).unwrap(), 1);
+        assert_eq!(writer.position(), 3);
+
+        assert_eq!(writer.seek(SeekFrom::Current(-2)).unwrap(), 1);
+        assert_eq!(writer.position(), 1);
+        assert_eq!(writer.write(&[3]).unwrap(), 1);
+        assert_eq!(writer.position(), 2);
+
+        assert_eq!(writer.seek(SeekFrom::End(-1)).unwrap(), 7);
+        assert_eq!(writer.position(), 7);
+        assert_eq!(writer.write(&[4]).unwrap(), 1);
+        assert_eq!(writer.position(), 8);
+    }
+    let b: &[_] = &[1, 3, 2, 0, 0, 0, 0, 4];
+    assert_eq!(buf, b);
+}
+
+#[test]
+fn test_buf_writer_error() {
+    let mut buf = [0 as u8; 2];
+    let mut writer = Cursor::new(&mut buf[..]);
+    assert_eq!(writer.write(&[0]).unwrap(), 1);
+    assert_eq!(writer.write(&[0, 0]).unwrap(), 1);
+    assert_eq!(writer.write(&[0, 0]).unwrap(), 0);
+}
+
+#[test]
+fn test_mem_reader() {
+    let mut reader = Cursor::new(vec![0, 1, 2, 3, 4, 5, 6, 7]);
+    let mut buf = [];
+    assert_eq!(reader.read(&mut buf).unwrap(), 0);
+    assert_eq!(reader.position(), 0);
+    let mut buf = [0];
+    assert_eq!(reader.read(&mut buf).unwrap(), 1);
+    assert_eq!(reader.position(), 1);
+    let b: &[_] = &[0];
+    assert_eq!(buf, b);
+    let mut buf = [0; 4];
+    assert_eq!(reader.read(&mut buf).unwrap(), 4);
+    assert_eq!(reader.position(), 5);
+    let b: &[_] = &[1, 2, 3, 4];
+    assert_eq!(buf, b);
+    assert_eq!(reader.read(&mut buf).unwrap(), 3);
+    let b: &[_] = &[5, 6, 7];
+    assert_eq!(&buf[..3], b);
+    assert_eq!(reader.read(&mut buf).unwrap(), 0);
+}
+
+#[test]
+fn test_mem_reader_vectored() {
+    let mut reader = Cursor::new(vec![0, 1, 2, 3, 4, 5, 6, 7]);
+    let mut buf = [];
+    assert_eq!(reader.read_vectored(&mut [IoSliceMut::new(&mut buf)]).unwrap(), 0);
+    assert_eq!(reader.position(), 0);
+    let mut buf = [0];
+    assert_eq!(
+        reader.read_vectored(&mut [IoSliceMut::new(&mut []), IoSliceMut::new(&mut buf),]).unwrap(),
+        1,
+    );
+    assert_eq!(reader.position(), 1);
+    let b: &[_] = &[0];
+    assert_eq!(buf, b);
+    let mut buf1 = [0; 4];
+    let mut buf2 = [0; 4];
+    assert_eq!(
+        reader
+            .read_vectored(&mut [IoSliceMut::new(&mut buf1), IoSliceMut::new(&mut buf2),])
+            .unwrap(),
+        7,
+    );
+    let b1: &[_] = &[1, 2, 3, 4];
+    let b2: &[_] = &[5, 6, 7];
+    assert_eq!(buf1, b1);
+    assert_eq!(&buf2[..3], b2);
+    assert_eq!(reader.read(&mut buf).unwrap(), 0);
+}
+
+#[test]
+fn test_boxed_slice_reader() {
+    let mut reader = Cursor::new(vec![0, 1, 2, 3, 4, 5, 6, 7].into_boxed_slice());
+    let mut buf = [];
+    assert_eq!(reader.read(&mut buf).unwrap(), 0);
+    assert_eq!(reader.position(), 0);
+    let mut buf = [0];
+    assert_eq!(reader.read(&mut buf).unwrap(), 1);
+    assert_eq!(reader.position(), 1);
+    let b: &[_] = &[0];
+    assert_eq!(buf, b);
+    let mut buf = [0; 4];
+    assert_eq!(reader.read(&mut buf).unwrap(), 4);
+    assert_eq!(reader.position(), 5);
+    let b: &[_] = &[1, 2, 3, 4];
+    assert_eq!(buf, b);
+    assert_eq!(reader.read(&mut buf).unwrap(), 3);
+    let b: &[_] = &[5, 6, 7];
+    assert_eq!(&buf[..3], b);
+    assert_eq!(reader.read(&mut buf).unwrap(), 0);
+}
+
+#[test]
+fn test_boxed_slice_reader_vectored() {
+    let mut reader = Cursor::new(vec![0, 1, 2, 3, 4, 5, 6, 7].into_boxed_slice());
+    let mut buf = [];
+    assert_eq!(reader.read_vectored(&mut [IoSliceMut::new(&mut buf)]).unwrap(), 0);
+    assert_eq!(reader.position(), 0);
+    let mut buf = [0];
+    assert_eq!(
+        reader.read_vectored(&mut [IoSliceMut::new(&mut []), IoSliceMut::new(&mut buf),]).unwrap(),
+        1,
+    );
+    assert_eq!(reader.position(), 1);
+    let b: &[_] = &[0];
+    assert_eq!(buf, b);
+    let mut buf1 = [0; 4];
+    let mut buf2 = [0; 4];
+    assert_eq!(
+        reader
+            .read_vectored(&mut [IoSliceMut::new(&mut buf1), IoSliceMut::new(&mut buf2)],)
+            .unwrap(),
+        7,
+    );
+    let b1: &[_] = &[1, 2, 3, 4];
+    let b2: &[_] = &[5, 6, 7];
+    assert_eq!(buf1, b1);
+    assert_eq!(&buf2[..3], b2);
+    assert_eq!(reader.read(&mut buf).unwrap(), 0);
+}
+
+#[test]
+fn read_to_end() {
+    let mut reader = Cursor::new(vec![0, 1, 2, 3, 4, 5, 6, 7]);
+    let mut v = Vec::new();
+    reader.read_to_end(&mut v).unwrap();
+    assert_eq!(v, [0, 1, 2, 3, 4, 5, 6, 7]);
+}
+
+#[test]
+fn test_slice_reader() {
+    let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
+    let reader = &mut &in_buf[..];
+    let mut buf = [];
+    assert_eq!(reader.read(&mut buf).unwrap(), 0);
+    let mut buf = [0];
+    assert_eq!(reader.read(&mut buf).unwrap(), 1);
+    assert_eq!(reader.len(), 7);
+    let b: &[_] = &[0];
+    assert_eq!(&buf[..], b);
+    let mut buf = [0; 4];
+    assert_eq!(reader.read(&mut buf).unwrap(), 4);
+    assert_eq!(reader.len(), 3);
+    let b: &[_] = &[1, 2, 3, 4];
+    assert_eq!(&buf[..], b);
+    assert_eq!(reader.read(&mut buf).unwrap(), 3);
+    let b: &[_] = &[5, 6, 7];
+    assert_eq!(&buf[..3], b);
+    assert_eq!(reader.read(&mut buf).unwrap(), 0);
+}
+
+#[test]
+fn test_slice_reader_vectored() {
+    let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
+    let reader = &mut &in_buf[..];
+    let mut buf = [];
+    assert_eq!(reader.read_vectored(&mut [IoSliceMut::new(&mut buf)]).unwrap(), 0);
+    let mut buf = [0];
+    assert_eq!(
+        reader.read_vectored(&mut [IoSliceMut::new(&mut []), IoSliceMut::new(&mut buf),]).unwrap(),
+        1,
+    );
+    assert_eq!(reader.len(), 7);
+    let b: &[_] = &[0];
+    assert_eq!(buf, b);
+    let mut buf1 = [0; 4];
+    let mut buf2 = [0; 4];
+    assert_eq!(
+        reader
+            .read_vectored(&mut [IoSliceMut::new(&mut buf1), IoSliceMut::new(&mut buf2)],)
+            .unwrap(),
+        7,
+    );
+    let b1: &[_] = &[1, 2, 3, 4];
+    let b2: &[_] = &[5, 6, 7];
+    assert_eq!(buf1, b1);
+    assert_eq!(&buf2[..3], b2);
+    assert_eq!(reader.read(&mut buf).unwrap(), 0);
+}
+
+#[test]
+fn test_read_exact() {
+    let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
+    let reader = &mut &in_buf[..];
+    let mut buf = [];
+    assert!(reader.read_exact(&mut buf).is_ok());
+    let mut buf = [8];
+    assert!(reader.read_exact(&mut buf).is_ok());
+    assert_eq!(buf[0], 0);
+    assert_eq!(reader.len(), 7);
+    let mut buf = [0, 0, 0, 0, 0, 0, 0];
+    assert!(reader.read_exact(&mut buf).is_ok());
+    assert_eq!(buf, [1, 2, 3, 4, 5, 6, 7]);
+    assert_eq!(reader.len(), 0);
+    let mut buf = [0];
+    assert!(reader.read_exact(&mut buf).is_err());
+}
+
+#[test]
+fn test_buf_reader() {
+    let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
+    let mut reader = Cursor::new(&in_buf[..]);
+    let mut buf = [];
+    assert_eq!(reader.read(&mut buf).unwrap(), 0);
+    assert_eq!(reader.position(), 0);
+    let mut buf = [0];
+    assert_eq!(reader.read(&mut buf).unwrap(), 1);
+    assert_eq!(reader.position(), 1);
+    let b: &[_] = &[0];
+    assert_eq!(buf, b);
+    let mut buf = [0; 4];
+    assert_eq!(reader.read(&mut buf).unwrap(), 4);
+    assert_eq!(reader.position(), 5);
+    let b: &[_] = &[1, 2, 3, 4];
+    assert_eq!(buf, b);
+    assert_eq!(reader.read(&mut buf).unwrap(), 3);
+    let b: &[_] = &[5, 6, 7];
+    assert_eq!(&buf[..3], b);
+    assert_eq!(reader.read(&mut buf).unwrap(), 0);
+}
+
+#[test]
+fn seek_past_end() {
+    let buf = [0xff];
+    let mut r = Cursor::new(&buf[..]);
+    assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10);
+    assert_eq!(r.read(&mut [0]).unwrap(), 0);
+
+    let mut r = Cursor::new(vec![10]);
+    assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10);
+    assert_eq!(r.read(&mut [0]).unwrap(), 0);
+
+    let mut buf = [0];
+    let mut r = Cursor::new(&mut buf[..]);
+    assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10);
+    assert_eq!(r.write(&[3]).unwrap(), 0);
+
+    let mut r = Cursor::new(vec![10].into_boxed_slice());
+    assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10);
+    assert_eq!(r.write(&[3]).unwrap(), 0);
+}
+
+#[test]
+fn seek_past_i64() {
+    let buf = [0xff];
+    let mut r = Cursor::new(&buf[..]);
+    assert_eq!(r.seek(SeekFrom::Start(6)).unwrap(), 6);
+    assert_eq!(r.seek(SeekFrom::Current(0x7ffffffffffffff0)).unwrap(), 0x7ffffffffffffff6);
+    assert_eq!(r.seek(SeekFrom::Current(0x10)).unwrap(), 0x8000000000000006);
+    assert_eq!(r.seek(SeekFrom::Current(0)).unwrap(), 0x8000000000000006);
+    assert!(r.seek(SeekFrom::Current(0x7ffffffffffffffd)).is_err());
+    assert_eq!(r.seek(SeekFrom::Current(-0x8000000000000000)).unwrap(), 6);
+
+    let mut r = Cursor::new(vec![10]);
+    assert_eq!(r.seek(SeekFrom::Start(6)).unwrap(), 6);
+    assert_eq!(r.seek(SeekFrom::Current(0x7ffffffffffffff0)).unwrap(), 0x7ffffffffffffff6);
+    assert_eq!(r.seek(SeekFrom::Current(0x10)).unwrap(), 0x8000000000000006);
+    assert_eq!(r.seek(SeekFrom::Current(0)).unwrap(), 0x8000000000000006);
+    assert!(r.seek(SeekFrom::Current(0x7ffffffffffffffd)).is_err());
+    assert_eq!(r.seek(SeekFrom::Current(-0x8000000000000000)).unwrap(), 6);
+
+    let mut buf = [0];
+    let mut r = Cursor::new(&mut buf[..]);
+    assert_eq!(r.seek(SeekFrom::Start(6)).unwrap(), 6);
+    assert_eq!(r.seek(SeekFrom::Current(0x7ffffffffffffff0)).unwrap(), 0x7ffffffffffffff6);
+    assert_eq!(r.seek(SeekFrom::Current(0x10)).unwrap(), 0x8000000000000006);
+    assert_eq!(r.seek(SeekFrom::Current(0)).unwrap(), 0x8000000000000006);
+    assert!(r.seek(SeekFrom::Current(0x7ffffffffffffffd)).is_err());
+    assert_eq!(r.seek(SeekFrom::Current(-0x8000000000000000)).unwrap(), 6);
+
+    let mut r = Cursor::new(vec![10].into_boxed_slice());
+    assert_eq!(r.seek(SeekFrom::Start(6)).unwrap(), 6);
+    assert_eq!(r.seek(SeekFrom::Current(0x7ffffffffffffff0)).unwrap(), 0x7ffffffffffffff6);
+    assert_eq!(r.seek(SeekFrom::Current(0x10)).unwrap(), 0x8000000000000006);
+    assert_eq!(r.seek(SeekFrom::Current(0)).unwrap(), 0x8000000000000006);
+    assert!(r.seek(SeekFrom::Current(0x7ffffffffffffffd)).is_err());
+    assert_eq!(r.seek(SeekFrom::Current(-0x8000000000000000)).unwrap(), 6);
+}
+
+#[test]
+fn seek_before_0() {
+    let buf = [0xff];
+    let mut r = Cursor::new(&buf[..]);
+    assert!(r.seek(SeekFrom::End(-2)).is_err());
+
+    let mut r = Cursor::new(vec![10]);
+    assert!(r.seek(SeekFrom::End(-2)).is_err());
+
+    let mut buf = [0];
+    let mut r = Cursor::new(&mut buf[..]);
+    assert!(r.seek(SeekFrom::End(-2)).is_err());
+
+    let mut r = Cursor::new(vec![10].into_boxed_slice());
+    assert!(r.seek(SeekFrom::End(-2)).is_err());
+}
+
+#[test]
+fn test_seekable_mem_writer() {
+    let mut writer = Cursor::new(Vec::<u8>::new());
+    assert_eq!(writer.position(), 0);
+    assert_eq!(writer.write(&[0]).unwrap(), 1);
+    assert_eq!(writer.position(), 1);
+    assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
+    assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
+    assert_eq!(writer.position(), 8);
+    let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
+    assert_eq!(&writer.get_ref()[..], b);
+
+    assert_eq!(writer.seek(SeekFrom::Start(0)).unwrap(), 0);
+    assert_eq!(writer.position(), 0);
+    assert_eq!(writer.write(&[3, 4]).unwrap(), 2);
+    let b: &[_] = &[3, 4, 2, 3, 4, 5, 6, 7];
+    assert_eq!(&writer.get_ref()[..], b);
+
+    assert_eq!(writer.seek(SeekFrom::Current(1)).unwrap(), 3);
+    assert_eq!(writer.write(&[0, 1]).unwrap(), 2);
+    let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 7];
+    assert_eq!(&writer.get_ref()[..], b);
+
+    assert_eq!(writer.seek(SeekFrom::End(-1)).unwrap(), 7);
+    assert_eq!(writer.write(&[1, 2]).unwrap(), 2);
+    let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2];
+    assert_eq!(&writer.get_ref()[..], b);
+
+    assert_eq!(writer.seek(SeekFrom::End(1)).unwrap(), 10);
+    assert_eq!(writer.write(&[1]).unwrap(), 1);
+    let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1];
+    assert_eq!(&writer.get_ref()[..], b);
+}
+
+#[test]
+fn vec_seek_past_end() {
+    let mut r = Cursor::new(Vec::new());
+    assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10);
+    assert_eq!(r.write(&[3]).unwrap(), 1);
+}
+
+#[test]
+fn vec_seek_before_0() {
+    let mut r = Cursor::new(Vec::new());
+    assert!(r.seek(SeekFrom::End(-2)).is_err());
+}
+
+#[test]
+#[cfg(target_pointer_width = "32")]
+fn vec_seek_and_write_past_usize_max() {
+    let mut c = Cursor::new(Vec::new());
+    c.set_position(usize::MAX as u64 + 1);
+    assert!(c.write_all(&[1, 2, 3]).is_err());
+}
+
+#[test]
+fn test_partial_eq() {
+    assert_eq!(Cursor::new(Vec::<u8>::new()), Cursor::new(Vec::<u8>::new()));
+}
+
+#[test]
+fn test_eq() {
+    struct AssertEq<T: Eq>(pub T);
+
+    let _: AssertEq<Cursor<Vec<u8>>> = AssertEq(Cursor::new(Vec::new()));
+}
diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs
index e6eda2caf75..ba0f0a0cd71 100644
--- a/library/std/src/io/error.rs
+++ b/library/std/src/io/error.rs
@@ -1,3 +1,6 @@
+#[cfg(test)]
+mod tests;
+
 use crate::convert::From;
 use crate::error;
 use crate::fmt;
@@ -574,60 +577,3 @@ fn _assert_error_is_sync_send() {
     fn _is_sync_send<T: Sync + Send>() {}
     _is_sync_send::<Error>();
 }
-
-#[cfg(test)]
-mod test {
-    use super::{Custom, Error, ErrorKind, Repr};
-    use crate::error;
-    use crate::fmt;
-    use crate::sys::decode_error_kind;
-    use crate::sys::os::error_string;
-
-    #[test]
-    fn test_debug_error() {
-        let code = 6;
-        let msg = error_string(code);
-        let kind = decode_error_kind(code);
-        let err = Error {
-            repr: Repr::Custom(box Custom {
-                kind: ErrorKind::InvalidInput,
-                error: box Error { repr: super::Repr::Os(code) },
-            }),
-        };
-        let expected = format!(
-            "Custom {{ \
-             kind: InvalidInput, \
-             error: Os {{ \
-             code: {:?}, \
-             kind: {:?}, \
-             message: {:?} \
-             }} \
-             }}",
-            code, kind, msg
-        );
-        assert_eq!(format!("{:?}", err), expected);
-    }
-
-    #[test]
-    fn test_downcasting() {
-        #[derive(Debug)]
-        struct TestError;
-
-        impl fmt::Display for TestError {
-            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                f.write_str("asdf")
-            }
-        }
-
-        impl error::Error for TestError {}
-
-        // we have to call all of these UFCS style right now since method
-        // resolution won't implicitly drop the Send+Sync bounds
-        let mut err = Error::new(ErrorKind::Other, TestError);
-        assert!(err.get_ref().unwrap().is::<TestError>());
-        assert_eq!("asdf", err.get_ref().unwrap().to_string());
-        assert!(err.get_mut().unwrap().is::<TestError>());
-        let extracted = err.into_inner().unwrap();
-        extracted.downcast::<TestError>().unwrap();
-    }
-}
diff --git a/library/std/src/io/error/tests.rs b/library/std/src/io/error/tests.rs
new file mode 100644
index 00000000000..0cce9368c80
--- /dev/null
+++ b/library/std/src/io/error/tests.rs
@@ -0,0 +1,53 @@
+use super::{Custom, Error, ErrorKind, Repr};
+use crate::error;
+use crate::fmt;
+use crate::sys::decode_error_kind;
+use crate::sys::os::error_string;
+
+#[test]
+fn test_debug_error() {
+    let code = 6;
+    let msg = error_string(code);
+    let kind = decode_error_kind(code);
+    let err = Error {
+        repr: Repr::Custom(box Custom {
+            kind: ErrorKind::InvalidInput,
+            error: box Error { repr: super::Repr::Os(code) },
+        }),
+    };
+    let expected = format!(
+        "Custom {{ \
+         kind: InvalidInput, \
+         error: Os {{ \
+         code: {:?}, \
+         kind: {:?}, \
+         message: {:?} \
+         }} \
+         }}",
+        code, kind, msg
+    );
+    assert_eq!(format!("{:?}", err), expected);
+}
+
+#[test]
+fn test_downcasting() {
+    #[derive(Debug)]
+    struct TestError;
+
+    impl fmt::Display for TestError {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+            f.write_str("asdf")
+        }
+    }
+
+    impl error::Error for TestError {}
+
+    // we have to call all of these UFCS style right now since method
+    // resolution won't implicitly drop the Send+Sync bounds
+    let mut err = Error::new(ErrorKind::Other, TestError);
+    assert!(err.get_ref().unwrap().is::<TestError>());
+    assert_eq!("asdf", err.get_ref().unwrap().to_string());
+    assert!(err.get_mut().unwrap().is::<TestError>());
+    let extracted = err.into_inner().unwrap();
+    extracted.downcast::<TestError>().unwrap();
+}
diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs
index 01dff0b3eb3..e09e7ba978e 100644
--- a/library/std/src/io/impls.rs
+++ b/library/std/src/io/impls.rs
@@ -1,3 +1,6 @@
+#[cfg(test)]
+mod tests;
+
 use crate::cmp;
 use crate::fmt;
 use crate::io::{
@@ -397,64 +400,3 @@ impl Write for Vec<u8> {
         Ok(())
     }
 }
-
-#[cfg(test)]
-mod tests {
-    use crate::io::prelude::*;
-
-    #[bench]
-    fn bench_read_slice(b: &mut test::Bencher) {
-        let buf = [5; 1024];
-        let mut dst = [0; 128];
-
-        b.iter(|| {
-            let mut rd = &buf[..];
-            for _ in 0..8 {
-                let _ = rd.read(&mut dst);
-                test::black_box(&dst);
-            }
-        })
-    }
-
-    #[bench]
-    fn bench_write_slice(b: &mut test::Bencher) {
-        let mut buf = [0; 1024];
-        let src = [5; 128];
-
-        b.iter(|| {
-            let mut wr = &mut buf[..];
-            for _ in 0..8 {
-                let _ = wr.write_all(&src);
-                test::black_box(&wr);
-            }
-        })
-    }
-
-    #[bench]
-    fn bench_read_vec(b: &mut test::Bencher) {
-        let buf = vec![5; 1024];
-        let mut dst = [0; 128];
-
-        b.iter(|| {
-            let mut rd = &buf[..];
-            for _ in 0..8 {
-                let _ = rd.read(&mut dst);
-                test::black_box(&dst);
-            }
-        })
-    }
-
-    #[bench]
-    fn bench_write_vec(b: &mut test::Bencher) {
-        let mut buf = Vec::with_capacity(1024);
-        let src = [5; 128];
-
-        b.iter(|| {
-            let mut wr = &mut buf[..];
-            for _ in 0..8 {
-                let _ = wr.write_all(&src);
-                test::black_box(&wr);
-            }
-        })
-    }
-}
diff --git a/library/std/src/io/impls/tests.rs b/library/std/src/io/impls/tests.rs
new file mode 100644
index 00000000000..d1cd84a67ad
--- /dev/null
+++ b/library/std/src/io/impls/tests.rs
@@ -0,0 +1,57 @@
+use crate::io::prelude::*;
+
+#[bench]
+fn bench_read_slice(b: &mut test::Bencher) {
+    let buf = [5; 1024];
+    let mut dst = [0; 128];
+
+    b.iter(|| {
+        let mut rd = &buf[..];
+        for _ in 0..8 {
+            let _ = rd.read(&mut dst);
+            test::black_box(&dst);
+        }
+    })
+}
+
+#[bench]
+fn bench_write_slice(b: &mut test::Bencher) {
+    let mut buf = [0; 1024];
+    let src = [5; 128];
+
+    b.iter(|| {
+        let mut wr = &mut buf[..];
+        for _ in 0..8 {
+            let _ = wr.write_all(&src);
+            test::black_box(&wr);
+        }
+    })
+}
+
+#[bench]
+fn bench_read_vec(b: &mut test::Bencher) {
+    let buf = vec![5; 1024];
+    let mut dst = [0; 128];
+
+    b.iter(|| {
+        let mut rd = &buf[..];
+        for _ in 0..8 {
+            let _ = rd.read(&mut dst);
+            test::black_box(&dst);
+        }
+    })
+}
+
+#[bench]
+fn bench_write_vec(b: &mut test::Bencher) {
+    let mut buf = Vec::with_capacity(1024);
+    let src = [5; 128];
+
+    b.iter(|| {
+        let mut wr = &mut buf[..];
+        for _ in 0..8 {
+            let _ = wr.write_all(&src);
+            test::black_box(&wr);
+        }
+    })
+}
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 462b696db40..adea8a804e3 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -249,6 +249,9 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+#[cfg(test)]
+mod tests;
+
 use crate::cmp;
 use crate::fmt;
 use crate::memchr;
@@ -2481,501 +2484,3 @@ impl<B: BufRead> Iterator for Lines<B> {
         }
     }
 }
-
-#[cfg(test)]
-mod tests {
-    use super::{repeat, Cursor, SeekFrom};
-    use crate::cmp::{self, min};
-    use crate::io::prelude::*;
-    use crate::io::{self, IoSlice, IoSliceMut};
-    use crate::ops::Deref;
-
-    #[test]
-    #[cfg_attr(target_os = "emscripten", ignore)]
-    fn read_until() {
-        let mut buf = Cursor::new(&b"12"[..]);
-        let mut v = Vec::new();
-        assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 2);
-        assert_eq!(v, b"12");
-
-        let mut buf = Cursor::new(&b"1233"[..]);
-        let mut v = Vec::new();
-        assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 3);
-        assert_eq!(v, b"123");
-        v.truncate(0);
-        assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 1);
-        assert_eq!(v, b"3");
-        v.truncate(0);
-        assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 0);
-        assert_eq!(v, []);
-    }
-
-    #[test]
-    fn split() {
-        let buf = Cursor::new(&b"12"[..]);
-        let mut s = buf.split(b'3');
-        assert_eq!(s.next().unwrap().unwrap(), vec![b'1', b'2']);
-        assert!(s.next().is_none());
-
-        let buf = Cursor::new(&b"1233"[..]);
-        let mut s = buf.split(b'3');
-        assert_eq!(s.next().unwrap().unwrap(), vec![b'1', b'2']);
-        assert_eq!(s.next().unwrap().unwrap(), vec![]);
-        assert!(s.next().is_none());
-    }
-
-    #[test]
-    fn read_line() {
-        let mut buf = Cursor::new(&b"12"[..]);
-        let mut v = String::new();
-        assert_eq!(buf.read_line(&mut v).unwrap(), 2);
-        assert_eq!(v, "12");
-
-        let mut buf = Cursor::new(&b"12\n\n"[..]);
-        let mut v = String::new();
-        assert_eq!(buf.read_line(&mut v).unwrap(), 3);
-        assert_eq!(v, "12\n");
-        v.truncate(0);
-        assert_eq!(buf.read_line(&mut v).unwrap(), 1);
-        assert_eq!(v, "\n");
-        v.truncate(0);
-        assert_eq!(buf.read_line(&mut v).unwrap(), 0);
-        assert_eq!(v, "");
-    }
-
-    #[test]
-    fn lines() {
-        let buf = Cursor::new(&b"12\r"[..]);
-        let mut s = buf.lines();
-        assert_eq!(s.next().unwrap().unwrap(), "12\r".to_string());
-        assert!(s.next().is_none());
-
-        let buf = Cursor::new(&b"12\r\n\n"[..]);
-        let mut s = buf.lines();
-        assert_eq!(s.next().unwrap().unwrap(), "12".to_string());
-        assert_eq!(s.next().unwrap().unwrap(), "".to_string());
-        assert!(s.next().is_none());
-    }
-
-    #[test]
-    fn read_to_end() {
-        let mut c = Cursor::new(&b""[..]);
-        let mut v = Vec::new();
-        assert_eq!(c.read_to_end(&mut v).unwrap(), 0);
-        assert_eq!(v, []);
-
-        let mut c = Cursor::new(&b"1"[..]);
-        let mut v = Vec::new();
-        assert_eq!(c.read_to_end(&mut v).unwrap(), 1);
-        assert_eq!(v, b"1");
-
-        let cap = 1024 * 1024;
-        let data = (0..cap).map(|i| (i / 3) as u8).collect::<Vec<_>>();
-        let mut v = Vec::new();
-        let (a, b) = data.split_at(data.len() / 2);
-        assert_eq!(Cursor::new(a).read_to_end(&mut v).unwrap(), a.len());
-        assert_eq!(Cursor::new(b).read_to_end(&mut v).unwrap(), b.len());
-        assert_eq!(v, data);
-    }
-
-    #[test]
-    fn read_to_string() {
-        let mut c = Cursor::new(&b""[..]);
-        let mut v = String::new();
-        assert_eq!(c.read_to_string(&mut v).unwrap(), 0);
-        assert_eq!(v, "");
-
-        let mut c = Cursor::new(&b"1"[..]);
-        let mut v = String::new();
-        assert_eq!(c.read_to_string(&mut v).unwrap(), 1);
-        assert_eq!(v, "1");
-
-        let mut c = Cursor::new(&b"\xff"[..]);
-        let mut v = String::new();
-        assert!(c.read_to_string(&mut v).is_err());
-    }
-
-    #[test]
-    fn read_exact() {
-        let mut buf = [0; 4];
-
-        let mut c = Cursor::new(&b""[..]);
-        assert_eq!(c.read_exact(&mut buf).unwrap_err().kind(), io::ErrorKind::UnexpectedEof);
-
-        let mut c = Cursor::new(&b"123"[..]).chain(Cursor::new(&b"456789"[..]));
-        c.read_exact(&mut buf).unwrap();
-        assert_eq!(&buf, b"1234");
-        c.read_exact(&mut buf).unwrap();
-        assert_eq!(&buf, b"5678");
-        assert_eq!(c.read_exact(&mut buf).unwrap_err().kind(), io::ErrorKind::UnexpectedEof);
-    }
-
-    #[test]
-    fn read_exact_slice() {
-        let mut buf = [0; 4];
-
-        let mut c = &b""[..];
-        assert_eq!(c.read_exact(&mut buf).unwrap_err().kind(), io::ErrorKind::UnexpectedEof);
-
-        let mut c = &b"123"[..];
-        assert_eq!(c.read_exact(&mut buf).unwrap_err().kind(), io::ErrorKind::UnexpectedEof);
-        // make sure the optimized (early returning) method is being used
-        assert_eq!(&buf, &[0; 4]);
-
-        let mut c = &b"1234"[..];
-        c.read_exact(&mut buf).unwrap();
-        assert_eq!(&buf, b"1234");
-
-        let mut c = &b"56789"[..];
-        c.read_exact(&mut buf).unwrap();
-        assert_eq!(&buf, b"5678");
-        assert_eq!(c, b"9");
-    }
-
-    #[test]
-    fn take_eof() {
-        struct R;
-
-        impl Read for R {
-            fn read(&mut self, _: &mut [u8]) -> io::Result<usize> {
-                Err(io::Error::new(io::ErrorKind::Other, ""))
-            }
-        }
-        impl BufRead for R {
-            fn fill_buf(&mut self) -> io::Result<&[u8]> {
-                Err(io::Error::new(io::ErrorKind::Other, ""))
-            }
-            fn consume(&mut self, _amt: usize) {}
-        }
-
-        let mut buf = [0; 1];
-        assert_eq!(0, R.take(0).read(&mut buf).unwrap());
-        assert_eq!(b"", R.take(0).fill_buf().unwrap());
-    }
-
-    fn cmp_bufread<Br1: BufRead, Br2: BufRead>(mut br1: Br1, mut br2: Br2, exp: &[u8]) {
-        let mut cat = Vec::new();
-        loop {
-            let consume = {
-                let buf1 = br1.fill_buf().unwrap();
-                let buf2 = br2.fill_buf().unwrap();
-                let minlen = if buf1.len() < buf2.len() { buf1.len() } else { buf2.len() };
-                assert_eq!(buf1[..minlen], buf2[..minlen]);
-                cat.extend_from_slice(&buf1[..minlen]);
-                minlen
-            };
-            if consume == 0 {
-                break;
-            }
-            br1.consume(consume);
-            br2.consume(consume);
-        }
-        assert_eq!(br1.fill_buf().unwrap().len(), 0);
-        assert_eq!(br2.fill_buf().unwrap().len(), 0);
-        assert_eq!(&cat[..], &exp[..])
-    }
-
-    #[test]
-    fn chain_bufread() {
-        let testdata = b"ABCDEFGHIJKL";
-        let chain1 =
-            (&testdata[..3]).chain(&testdata[3..6]).chain(&testdata[6..9]).chain(&testdata[9..]);
-        let chain2 = (&testdata[..4]).chain(&testdata[4..8]).chain(&testdata[8..]);
-        cmp_bufread(chain1, chain2, &testdata[..]);
-    }
-
-    #[test]
-    fn chain_zero_length_read_is_not_eof() {
-        let a = b"A";
-        let b = b"B";
-        let mut s = String::new();
-        let mut chain = (&a[..]).chain(&b[..]);
-        chain.read(&mut []).unwrap();
-        chain.read_to_string(&mut s).unwrap();
-        assert_eq!("AB", s);
-    }
-
-    #[bench]
-    #[cfg_attr(target_os = "emscripten", ignore)]
-    fn bench_read_to_end(b: &mut test::Bencher) {
-        b.iter(|| {
-            let mut lr = repeat(1).take(10000000);
-            let mut vec = Vec::with_capacity(1024);
-            super::read_to_end(&mut lr, &mut vec)
-        });
-    }
-
-    #[test]
-    fn seek_len() -> io::Result<()> {
-        let mut c = Cursor::new(vec![0; 15]);
-        assert_eq!(c.stream_len()?, 15);
-
-        c.seek(SeekFrom::End(0))?;
-        let old_pos = c.stream_position()?;
-        assert_eq!(c.stream_len()?, 15);
-        assert_eq!(c.stream_position()?, old_pos);
-
-        c.seek(SeekFrom::Start(7))?;
-        c.seek(SeekFrom::Current(2))?;
-        let old_pos = c.stream_position()?;
-        assert_eq!(c.stream_len()?, 15);
-        assert_eq!(c.stream_position()?, old_pos);
-
-        Ok(())
-    }
-
-    #[test]
-    fn seek_position() -> io::Result<()> {
-        // All `asserts` are duplicated here to make sure the method does not
-        // change anything about the seek state.
-        let mut c = Cursor::new(vec![0; 15]);
-        assert_eq!(c.stream_position()?, 0);
-        assert_eq!(c.stream_position()?, 0);
-
-        c.seek(SeekFrom::End(0))?;
-        assert_eq!(c.stream_position()?, 15);
-        assert_eq!(c.stream_position()?, 15);
-
-        c.seek(SeekFrom::Start(7))?;
-        c.seek(SeekFrom::Current(2))?;
-        assert_eq!(c.stream_position()?, 9);
-        assert_eq!(c.stream_position()?, 9);
-
-        c.seek(SeekFrom::End(-3))?;
-        c.seek(SeekFrom::Current(1))?;
-        c.seek(SeekFrom::Current(-5))?;
-        assert_eq!(c.stream_position()?, 8);
-        assert_eq!(c.stream_position()?, 8);
-
-        Ok(())
-    }
-
-    // A simple example reader which uses the default implementation of
-    // read_to_end.
-    struct ExampleSliceReader<'a> {
-        slice: &'a [u8],
-    }
-
-    impl<'a> Read for ExampleSliceReader<'a> {
-        fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-            let len = cmp::min(self.slice.len(), buf.len());
-            buf[..len].copy_from_slice(&self.slice[..len]);
-            self.slice = &self.slice[len..];
-            Ok(len)
-        }
-    }
-
-    #[test]
-    fn test_read_to_end_capacity() -> io::Result<()> {
-        let input = &b"foo"[..];
-
-        // read_to_end() generally needs to over-allocate, both for efficiency
-        // and so that it can distinguish EOF. Assert that this is the case
-        // with this simple ExampleSliceReader struct, which uses the default
-        // implementation of read_to_end. Even though vec1 is allocated with
-        // exactly enough capacity for the read, read_to_end will allocate more
-        // space here.
-        let mut vec1 = Vec::with_capacity(input.len());
-        ExampleSliceReader { slice: input }.read_to_end(&mut vec1)?;
-        assert_eq!(vec1.len(), input.len());
-        assert!(vec1.capacity() > input.len(), "allocated more");
-
-        // However, std::io::Take includes an implementation of read_to_end
-        // that will not allocate when the limit has already been reached. In
-        // this case, vec2 never grows.
-        let mut vec2 = Vec::with_capacity(input.len());
-        ExampleSliceReader { slice: input }.take(input.len() as u64).read_to_end(&mut vec2)?;
-        assert_eq!(vec2.len(), input.len());
-        assert_eq!(vec2.capacity(), input.len(), "did not allocate more");
-
-        Ok(())
-    }
-
-    #[test]
-    fn io_slice_mut_advance() {
-        let mut buf1 = [1; 8];
-        let mut buf2 = [2; 16];
-        let mut buf3 = [3; 8];
-        let mut bufs = &mut [
-            IoSliceMut::new(&mut buf1),
-            IoSliceMut::new(&mut buf2),
-            IoSliceMut::new(&mut buf3),
-        ][..];
-
-        // Only in a single buffer..
-        bufs = IoSliceMut::advance(bufs, 1);
-        assert_eq!(bufs[0].deref(), [1; 7].as_ref());
-        assert_eq!(bufs[1].deref(), [2; 16].as_ref());
-        assert_eq!(bufs[2].deref(), [3; 8].as_ref());
-
-        // Removing a buffer, leaving others as is.
-        bufs = IoSliceMut::advance(bufs, 7);
-        assert_eq!(bufs[0].deref(), [2; 16].as_ref());
-        assert_eq!(bufs[1].deref(), [3; 8].as_ref());
-
-        // Removing a buffer and removing from the next buffer.
-        bufs = IoSliceMut::advance(bufs, 18);
-        assert_eq!(bufs[0].deref(), [3; 6].as_ref());
-    }
-
-    #[test]
-    fn io_slice_mut_advance_empty_slice() {
-        let empty_bufs = &mut [][..];
-        // Shouldn't panic.
-        IoSliceMut::advance(empty_bufs, 1);
-    }
-
-    #[test]
-    fn io_slice_mut_advance_beyond_total_length() {
-        let mut buf1 = [1; 8];
-        let mut bufs = &mut [IoSliceMut::new(&mut buf1)][..];
-
-        // Going beyond the total length should be ok.
-        bufs = IoSliceMut::advance(bufs, 9);
-        assert!(bufs.is_empty());
-    }
-
-    #[test]
-    fn io_slice_advance() {
-        let buf1 = [1; 8];
-        let buf2 = [2; 16];
-        let buf3 = [3; 8];
-        let mut bufs = &mut [IoSlice::new(&buf1), IoSlice::new(&buf2), IoSlice::new(&buf3)][..];
-
-        // Only in a single buffer..
-        bufs = IoSlice::advance(bufs, 1);
-        assert_eq!(bufs[0].deref(), [1; 7].as_ref());
-        assert_eq!(bufs[1].deref(), [2; 16].as_ref());
-        assert_eq!(bufs[2].deref(), [3; 8].as_ref());
-
-        // Removing a buffer, leaving others as is.
-        bufs = IoSlice::advance(bufs, 7);
-        assert_eq!(bufs[0].deref(), [2; 16].as_ref());
-        assert_eq!(bufs[1].deref(), [3; 8].as_ref());
-
-        // Removing a buffer and removing from the next buffer.
-        bufs = IoSlice::advance(bufs, 18);
-        assert_eq!(bufs[0].deref(), [3; 6].as_ref());
-    }
-
-    #[test]
-    fn io_slice_advance_empty_slice() {
-        let empty_bufs = &mut [][..];
-        // Shouldn't panic.
-        IoSlice::advance(empty_bufs, 1);
-    }
-
-    #[test]
-    fn io_slice_advance_beyond_total_length() {
-        let buf1 = [1; 8];
-        let mut bufs = &mut [IoSlice::new(&buf1)][..];
-
-        // Going beyond the total length should be ok.
-        bufs = IoSlice::advance(bufs, 9);
-        assert!(bufs.is_empty());
-    }
-
-    /// Create a new writer that reads from at most `n_bufs` and reads
-    /// `per_call` bytes (in total) per call to write.
-    fn test_writer(n_bufs: usize, per_call: usize) -> TestWriter {
-        TestWriter { n_bufs, per_call, written: Vec::new() }
-    }
-
-    struct TestWriter {
-        n_bufs: usize,
-        per_call: usize,
-        written: Vec<u8>,
-    }
-
-    impl Write for TestWriter {
-        fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-            self.write_vectored(&[IoSlice::new(buf)])
-        }
-
-        fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-            let mut left = self.per_call;
-            let mut written = 0;
-            for buf in bufs.iter().take(self.n_bufs) {
-                let n = min(left, buf.len());
-                self.written.extend_from_slice(&buf[0..n]);
-                left -= n;
-                written += n;
-            }
-            Ok(written)
-        }
-
-        fn flush(&mut self) -> io::Result<()> {
-            Ok(())
-        }
-    }
-
-    #[test]
-    fn test_writer_read_from_one_buf() {
-        let mut writer = test_writer(1, 2);
-
-        assert_eq!(writer.write(&[]).unwrap(), 0);
-        assert_eq!(writer.write_vectored(&[]).unwrap(), 0);
-
-        // Read at most 2 bytes.
-        assert_eq!(writer.write(&[1, 1, 1]).unwrap(), 2);
-        let bufs = &[IoSlice::new(&[2, 2, 2])];
-        assert_eq!(writer.write_vectored(bufs).unwrap(), 2);
-
-        // Only read from first buf.
-        let bufs = &[IoSlice::new(&[3]), IoSlice::new(&[4, 4])];
-        assert_eq!(writer.write_vectored(bufs).unwrap(), 1);
-
-        assert_eq!(writer.written, &[1, 1, 2, 2, 3]);
-    }
-
-    #[test]
-    fn test_writer_read_from_multiple_bufs() {
-        let mut writer = test_writer(3, 3);
-
-        // Read at most 3 bytes from two buffers.
-        let bufs = &[IoSlice::new(&[1]), IoSlice::new(&[2, 2, 2])];
-        assert_eq!(writer.write_vectored(bufs).unwrap(), 3);
-
-        // Read at most 3 bytes from three buffers.
-        let bufs = &[IoSlice::new(&[3]), IoSlice::new(&[4]), IoSlice::new(&[5, 5])];
-        assert_eq!(writer.write_vectored(bufs).unwrap(), 3);
-
-        assert_eq!(writer.written, &[1, 2, 2, 3, 4, 5]);
-    }
-
-    #[test]
-    fn test_write_all_vectored() {
-        #[rustfmt::skip] // Becomes unreadable otherwise.
-        let tests: Vec<(_, &'static [u8])> = vec![
-            (vec![], &[]),
-            (vec![IoSlice::new(&[]), IoSlice::new(&[])], &[]),
-            (vec![IoSlice::new(&[1])], &[1]),
-            (vec![IoSlice::new(&[1, 2])], &[1, 2]),
-            (vec![IoSlice::new(&[1, 2, 3])], &[1, 2, 3]),
-            (vec![IoSlice::new(&[1, 2, 3, 4])], &[1, 2, 3, 4]),
-            (vec![IoSlice::new(&[1, 2, 3, 4, 5])], &[1, 2, 3, 4, 5]),
-            (vec![IoSlice::new(&[1]), IoSlice::new(&[2])], &[1, 2]),
-            (vec![IoSlice::new(&[1]), IoSlice::new(&[2, 2])], &[1, 2, 2]),
-            (vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2])], &[1, 1, 2, 2]),
-            (vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2, 2])], &[1, 1, 2, 2, 2]),
-            (vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2, 2])], &[1, 1, 2, 2, 2]),
-            (vec![IoSlice::new(&[1, 1, 1]), IoSlice::new(&[2, 2, 2])], &[1, 1, 1, 2, 2, 2]),
-            (vec![IoSlice::new(&[1, 1, 1]), IoSlice::new(&[2, 2, 2, 2])], &[1, 1, 1, 2, 2, 2, 2]),
-            (vec![IoSlice::new(&[1, 1, 1, 1]), IoSlice::new(&[2, 2, 2, 2])], &[1, 1, 1, 1, 2, 2, 2, 2]),
-            (vec![IoSlice::new(&[1]), IoSlice::new(&[2]), IoSlice::new(&[3])], &[1, 2, 3]),
-            (vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2]), IoSlice::new(&[3, 3])], &[1, 1, 2, 2, 3, 3]),
-            (vec![IoSlice::new(&[1]), IoSlice::new(&[2, 2]), IoSlice::new(&[3, 3, 3])], &[1, 2, 2, 3, 3, 3]),
-            (vec![IoSlice::new(&[1, 1, 1]), IoSlice::new(&[2, 2, 2]), IoSlice::new(&[3, 3, 3])], &[1, 1, 1, 2, 2, 2, 3, 3, 3]),
-        ];
-
-        let writer_configs = &[(1, 1), (1, 2), (1, 3), (2, 2), (2, 3), (3, 3)];
-
-        for (n_bufs, per_call) in writer_configs.iter().copied() {
-            for (mut input, wanted) in tests.clone().into_iter() {
-                let mut writer = test_writer(n_bufs, per_call);
-                assert!(writer.write_all_vectored(&mut *input).is_ok());
-                assert_eq!(&*writer.written, &*wanted);
-            }
-        }
-    }
-}
diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs
index 3943c66aad5..9974b65f1e1 100644
--- a/library/std/src/io/stdio.rs
+++ b/library/std/src/io/stdio.rs
@@ -1,5 +1,8 @@
 #![cfg_attr(test, allow(unused))]
 
+#[cfg(test)]
+mod tests;
+
 use crate::io::prelude::*;
 
 use crate::cell::RefCell;
@@ -920,54 +923,3 @@ pub fn _eprint(args: fmt::Arguments<'_>) {
 
 #[cfg(test)]
 pub use realstd::io::{_eprint, _print};
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use crate::panic::{RefUnwindSafe, UnwindSafe};
-    use crate::thread;
-
-    #[test]
-    fn stdout_unwind_safe() {
-        assert_unwind_safe::<Stdout>();
-    }
-    #[test]
-    fn stdoutlock_unwind_safe() {
-        assert_unwind_safe::<StdoutLock<'_>>();
-        assert_unwind_safe::<StdoutLock<'static>>();
-    }
-    #[test]
-    fn stderr_unwind_safe() {
-        assert_unwind_safe::<Stderr>();
-    }
-    #[test]
-    fn stderrlock_unwind_safe() {
-        assert_unwind_safe::<StderrLock<'_>>();
-        assert_unwind_safe::<StderrLock<'static>>();
-    }
-
-    fn assert_unwind_safe<T: UnwindSafe + RefUnwindSafe>() {}
-
-    #[test]
-    #[cfg_attr(target_os = "emscripten", ignore)]
-    fn panic_doesnt_poison() {
-        thread::spawn(|| {
-            let _a = stdin();
-            let _a = _a.lock();
-            let _a = stdout();
-            let _a = _a.lock();
-            let _a = stderr();
-            let _a = _a.lock();
-            panic!();
-        })
-        .join()
-        .unwrap_err();
-
-        let _a = stdin();
-        let _a = _a.lock();
-        let _a = stdout();
-        let _a = _a.lock();
-        let _a = stderr();
-        let _a = _a.lock();
-    }
-}
diff --git a/library/std/src/io/stdio/tests.rs b/library/std/src/io/stdio/tests.rs
new file mode 100644
index 00000000000..04af500268f
--- /dev/null
+++ b/library/std/src/io/stdio/tests.rs
@@ -0,0 +1,47 @@
+use super::*;
+use crate::panic::{RefUnwindSafe, UnwindSafe};
+use crate::thread;
+
+#[test]
+fn stdout_unwind_safe() {
+    assert_unwind_safe::<Stdout>();
+}
+#[test]
+fn stdoutlock_unwind_safe() {
+    assert_unwind_safe::<StdoutLock<'_>>();
+    assert_unwind_safe::<StdoutLock<'static>>();
+}
+#[test]
+fn stderr_unwind_safe() {
+    assert_unwind_safe::<Stderr>();
+}
+#[test]
+fn stderrlock_unwind_safe() {
+    assert_unwind_safe::<StderrLock<'_>>();
+    assert_unwind_safe::<StderrLock<'static>>();
+}
+
+fn assert_unwind_safe<T: UnwindSafe + RefUnwindSafe>() {}
+
+#[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
+fn panic_doesnt_poison() {
+    thread::spawn(|| {
+        let _a = stdin();
+        let _a = _a.lock();
+        let _a = stdout();
+        let _a = _a.lock();
+        let _a = stderr();
+        let _a = _a.lock();
+        panic!();
+    })
+    .join()
+    .unwrap_err();
+
+    let _a = stdin();
+    let _a = _a.lock();
+    let _a = stdout();
+    let _a = _a.lock();
+    let _a = stderr();
+    let _a = _a.lock();
+}
diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs
new file mode 100644
index 00000000000..913b28538b7
--- /dev/null
+++ b/library/std/src/io/tests.rs
@@ -0,0 +1,494 @@
+use super::{repeat, Cursor, SeekFrom};
+use crate::cmp::{self, min};
+use crate::io::prelude::*;
+use crate::io::{self, IoSlice, IoSliceMut};
+use crate::ops::Deref;
+
+#[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
+fn read_until() {
+    let mut buf = Cursor::new(&b"12"[..]);
+    let mut v = Vec::new();
+    assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 2);
+    assert_eq!(v, b"12");
+
+    let mut buf = Cursor::new(&b"1233"[..]);
+    let mut v = Vec::new();
+    assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 3);
+    assert_eq!(v, b"123");
+    v.truncate(0);
+    assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 1);
+    assert_eq!(v, b"3");
+    v.truncate(0);
+    assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 0);
+    assert_eq!(v, []);
+}
+
+#[test]
+fn split() {
+    let buf = Cursor::new(&b"12"[..]);
+    let mut s = buf.split(b'3');
+    assert_eq!(s.next().unwrap().unwrap(), vec![b'1', b'2']);
+    assert!(s.next().is_none());
+
+    let buf = Cursor::new(&b"1233"[..]);
+    let mut s = buf.split(b'3');
+    assert_eq!(s.next().unwrap().unwrap(), vec![b'1', b'2']);
+    assert_eq!(s.next().unwrap().unwrap(), vec![]);
+    assert!(s.next().is_none());
+}
+
+#[test]
+fn read_line() {
+    let mut buf = Cursor::new(&b"12"[..]);
+    let mut v = String::new();
+    assert_eq!(buf.read_line(&mut v).unwrap(), 2);
+    assert_eq!(v, "12");
+
+    let mut buf = Cursor::new(&b"12\n\n"[..]);
+    let mut v = String::new();
+    assert_eq!(buf.read_line(&mut v).unwrap(), 3);
+    assert_eq!(v, "12\n");
+    v.truncate(0);
+    assert_eq!(buf.read_line(&mut v).unwrap(), 1);
+    assert_eq!(v, "\n");
+    v.truncate(0);
+    assert_eq!(buf.read_line(&mut v).unwrap(), 0);
+    assert_eq!(v, "");
+}
+
+#[test]
+fn lines() {
+    let buf = Cursor::new(&b"12\r"[..]);
+    let mut s = buf.lines();
+    assert_eq!(s.next().unwrap().unwrap(), "12\r".to_string());
+    assert!(s.next().is_none());
+
+    let buf = Cursor::new(&b"12\r\n\n"[..]);
+    let mut s = buf.lines();
+    assert_eq!(s.next().unwrap().unwrap(), "12".to_string());
+    assert_eq!(s.next().unwrap().unwrap(), "".to_string());
+    assert!(s.next().is_none());
+}
+
+#[test]
+fn read_to_end() {
+    let mut c = Cursor::new(&b""[..]);
+    let mut v = Vec::new();
+    assert_eq!(c.read_to_end(&mut v).unwrap(), 0);
+    assert_eq!(v, []);
+
+    let mut c = Cursor::new(&b"1"[..]);
+    let mut v = Vec::new();
+    assert_eq!(c.read_to_end(&mut v).unwrap(), 1);
+    assert_eq!(v, b"1");
+
+    let cap = 1024 * 1024;
+    let data = (0..cap).map(|i| (i / 3) as u8).collect::<Vec<_>>();
+    let mut v = Vec::new();
+    let (a, b) = data.split_at(data.len() / 2);
+    assert_eq!(Cursor::new(a).read_to_end(&mut v).unwrap(), a.len());
+    assert_eq!(Cursor::new(b).read_to_end(&mut v).unwrap(), b.len());
+    assert_eq!(v, data);
+}
+
+#[test]
+fn read_to_string() {
+    let mut c = Cursor::new(&b""[..]);
+    let mut v = String::new();
+    assert_eq!(c.read_to_string(&mut v).unwrap(), 0);
+    assert_eq!(v, "");
+
+    let mut c = Cursor::new(&b"1"[..]);
+    let mut v = String::new();
+    assert_eq!(c.read_to_string(&mut v).unwrap(), 1);
+    assert_eq!(v, "1");
+
+    let mut c = Cursor::new(&b"\xff"[..]);
+    let mut v = String::new();
+    assert!(c.read_to_string(&mut v).is_err());
+}
+
+#[test]
+fn read_exact() {
+    let mut buf = [0; 4];
+
+    let mut c = Cursor::new(&b""[..]);
+    assert_eq!(c.read_exact(&mut buf).unwrap_err().kind(), io::ErrorKind::UnexpectedEof);
+
+    let mut c = Cursor::new(&b"123"[..]).chain(Cursor::new(&b"456789"[..]));
+    c.read_exact(&mut buf).unwrap();
+    assert_eq!(&buf, b"1234");
+    c.read_exact(&mut buf).unwrap();
+    assert_eq!(&buf, b"5678");
+    assert_eq!(c.read_exact(&mut buf).unwrap_err().kind(), io::ErrorKind::UnexpectedEof);
+}
+
+#[test]
+fn read_exact_slice() {
+    let mut buf = [0; 4];
+
+    let mut c = &b""[..];
+    assert_eq!(c.read_exact(&mut buf).unwrap_err().kind(), io::ErrorKind::UnexpectedEof);
+
+    let mut c = &b"123"[..];
+    assert_eq!(c.read_exact(&mut buf).unwrap_err().kind(), io::ErrorKind::UnexpectedEof);
+    // make sure the optimized (early returning) method is being used
+    assert_eq!(&buf, &[0; 4]);
+
+    let mut c = &b"1234"[..];
+    c.read_exact(&mut buf).unwrap();
+    assert_eq!(&buf, b"1234");
+
+    let mut c = &b"56789"[..];
+    c.read_exact(&mut buf).unwrap();
+    assert_eq!(&buf, b"5678");
+    assert_eq!(c, b"9");
+}
+
+#[test]
+fn take_eof() {
+    struct R;
+
+    impl Read for R {
+        fn read(&mut self, _: &mut [u8]) -> io::Result<usize> {
+            Err(io::Error::new(io::ErrorKind::Other, ""))
+        }
+    }
+    impl BufRead for R {
+        fn fill_buf(&mut self) -> io::Result<&[u8]> {
+            Err(io::Error::new(io::ErrorKind::Other, ""))
+        }
+        fn consume(&mut self, _amt: usize) {}
+    }
+
+    let mut buf = [0; 1];
+    assert_eq!(0, R.take(0).read(&mut buf).unwrap());
+    assert_eq!(b"", R.take(0).fill_buf().unwrap());
+}
+
+fn cmp_bufread<Br1: BufRead, Br2: BufRead>(mut br1: Br1, mut br2: Br2, exp: &[u8]) {
+    let mut cat = Vec::new();
+    loop {
+        let consume = {
+            let buf1 = br1.fill_buf().unwrap();
+            let buf2 = br2.fill_buf().unwrap();
+            let minlen = if buf1.len() < buf2.len() { buf1.len() } else { buf2.len() };
+            assert_eq!(buf1[..minlen], buf2[..minlen]);
+            cat.extend_from_slice(&buf1[..minlen]);
+            minlen
+        };
+        if consume == 0 {
+            break;
+        }
+        br1.consume(consume);
+        br2.consume(consume);
+    }
+    assert_eq!(br1.fill_buf().unwrap().len(), 0);
+    assert_eq!(br2.fill_buf().unwrap().len(), 0);
+    assert_eq!(&cat[..], &exp[..])
+}
+
+#[test]
+fn chain_bufread() {
+    let testdata = b"ABCDEFGHIJKL";
+    let chain1 =
+        (&testdata[..3]).chain(&testdata[3..6]).chain(&testdata[6..9]).chain(&testdata[9..]);
+    let chain2 = (&testdata[..4]).chain(&testdata[4..8]).chain(&testdata[8..]);
+    cmp_bufread(chain1, chain2, &testdata[..]);
+}
+
+#[test]
+fn chain_zero_length_read_is_not_eof() {
+    let a = b"A";
+    let b = b"B";
+    let mut s = String::new();
+    let mut chain = (&a[..]).chain(&b[..]);
+    chain.read(&mut []).unwrap();
+    chain.read_to_string(&mut s).unwrap();
+    assert_eq!("AB", s);
+}
+
+#[bench]
+#[cfg_attr(target_os = "emscripten", ignore)]
+fn bench_read_to_end(b: &mut test::Bencher) {
+    b.iter(|| {
+        let mut lr = repeat(1).take(10000000);
+        let mut vec = Vec::with_capacity(1024);
+        super::read_to_end(&mut lr, &mut vec)
+    });
+}
+
+#[test]
+fn seek_len() -> io::Result<()> {
+    let mut c = Cursor::new(vec![0; 15]);
+    assert_eq!(c.stream_len()?, 15);
+
+    c.seek(SeekFrom::End(0))?;
+    let old_pos = c.stream_position()?;
+    assert_eq!(c.stream_len()?, 15);
+    assert_eq!(c.stream_position()?, old_pos);
+
+    c.seek(SeekFrom::Start(7))?;
+    c.seek(SeekFrom::Current(2))?;
+    let old_pos = c.stream_position()?;
+    assert_eq!(c.stream_len()?, 15);
+    assert_eq!(c.stream_position()?, old_pos);
+
+    Ok(())
+}
+
+#[test]
+fn seek_position() -> io::Result<()> {
+    // All `asserts` are duplicated here to make sure the method does not
+    // change anything about the seek state.
+    let mut c = Cursor::new(vec![0; 15]);
+    assert_eq!(c.stream_position()?, 0);
+    assert_eq!(c.stream_position()?, 0);
+
+    c.seek(SeekFrom::End(0))?;
+    assert_eq!(c.stream_position()?, 15);
+    assert_eq!(c.stream_position()?, 15);
+
+    c.seek(SeekFrom::Start(7))?;
+    c.seek(SeekFrom::Current(2))?;
+    assert_eq!(c.stream_position()?, 9);
+    assert_eq!(c.stream_position()?, 9);
+
+    c.seek(SeekFrom::End(-3))?;
+    c.seek(SeekFrom::Current(1))?;
+    c.seek(SeekFrom::Current(-5))?;
+    assert_eq!(c.stream_position()?, 8);
+    assert_eq!(c.stream_position()?, 8);
+
+    Ok(())
+}
+
+// A simple example reader which uses the default implementation of
+// read_to_end.
+struct ExampleSliceReader<'a> {
+    slice: &'a [u8],
+}
+
+impl<'a> Read for ExampleSliceReader<'a> {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        let len = cmp::min(self.slice.len(), buf.len());
+        buf[..len].copy_from_slice(&self.slice[..len]);
+        self.slice = &self.slice[len..];
+        Ok(len)
+    }
+}
+
+#[test]
+fn test_read_to_end_capacity() -> io::Result<()> {
+    let input = &b"foo"[..];
+
+    // read_to_end() generally needs to over-allocate, both for efficiency
+    // and so that it can distinguish EOF. Assert that this is the case
+    // with this simple ExampleSliceReader struct, which uses the default
+    // implementation of read_to_end. Even though vec1 is allocated with
+    // exactly enough capacity for the read, read_to_end will allocate more
+    // space here.
+    let mut vec1 = Vec::with_capacity(input.len());
+    ExampleSliceReader { slice: input }.read_to_end(&mut vec1)?;
+    assert_eq!(vec1.len(), input.len());
+    assert!(vec1.capacity() > input.len(), "allocated more");
+
+    // However, std::io::Take includes an implementation of read_to_end
+    // that will not allocate when the limit has already been reached. In
+    // this case, vec2 never grows.
+    let mut vec2 = Vec::with_capacity(input.len());
+    ExampleSliceReader { slice: input }.take(input.len() as u64).read_to_end(&mut vec2)?;
+    assert_eq!(vec2.len(), input.len());
+    assert_eq!(vec2.capacity(), input.len(), "did not allocate more");
+
+    Ok(())
+}
+
+#[test]
+fn io_slice_mut_advance() {
+    let mut buf1 = [1; 8];
+    let mut buf2 = [2; 16];
+    let mut buf3 = [3; 8];
+    let mut bufs = &mut [
+        IoSliceMut::new(&mut buf1),
+        IoSliceMut::new(&mut buf2),
+        IoSliceMut::new(&mut buf3),
+    ][..];
+
+    // Only in a single buffer..
+    bufs = IoSliceMut::advance(bufs, 1);
+    assert_eq!(bufs[0].deref(), [1; 7].as_ref());
+    assert_eq!(bufs[1].deref(), [2; 16].as_ref());
+    assert_eq!(bufs[2].deref(), [3; 8].as_ref());
+
+    // Removing a buffer, leaving others as is.
+    bufs = IoSliceMut::advance(bufs, 7);
+    assert_eq!(bufs[0].deref(), [2; 16].as_ref());
+    assert_eq!(bufs[1].deref(), [3; 8].as_ref());
+
+    // Removing a buffer and removing from the next buffer.
+    bufs = IoSliceMut::advance(bufs, 18);
+    assert_eq!(bufs[0].deref(), [3; 6].as_ref());
+}
+
+#[test]
+fn io_slice_mut_advance_empty_slice() {
+    let empty_bufs = &mut [][..];
+    // Shouldn't panic.
+    IoSliceMut::advance(empty_bufs, 1);
+}
+
+#[test]
+fn io_slice_mut_advance_beyond_total_length() {
+    let mut buf1 = [1; 8];
+    let mut bufs = &mut [IoSliceMut::new(&mut buf1)][..];
+
+    // Going beyond the total length should be ok.
+    bufs = IoSliceMut::advance(bufs, 9);
+    assert!(bufs.is_empty());
+}
+
+#[test]
+fn io_slice_advance() {
+    let buf1 = [1; 8];
+    let buf2 = [2; 16];
+    let buf3 = [3; 8];
+    let mut bufs = &mut [IoSlice::new(&buf1), IoSlice::new(&buf2), IoSlice::new(&buf3)][..];
+
+    // Only in a single buffer..
+    bufs = IoSlice::advance(bufs, 1);
+    assert_eq!(bufs[0].deref(), [1; 7].as_ref());
+    assert_eq!(bufs[1].deref(), [2; 16].as_ref());
+    assert_eq!(bufs[2].deref(), [3; 8].as_ref());
+
+    // Removing a buffer, leaving others as is.
+    bufs = IoSlice::advance(bufs, 7);
+    assert_eq!(bufs[0].deref(), [2; 16].as_ref());
+    assert_eq!(bufs[1].deref(), [3; 8].as_ref());
+
+    // Removing a buffer and removing from the next buffer.
+    bufs = IoSlice::advance(bufs, 18);
+    assert_eq!(bufs[0].deref(), [3; 6].as_ref());
+}
+
+#[test]
+fn io_slice_advance_empty_slice() {
+    let empty_bufs = &mut [][..];
+    // Shouldn't panic.
+    IoSlice::advance(empty_bufs, 1);
+}
+
+#[test]
+fn io_slice_advance_beyond_total_length() {
+    let buf1 = [1; 8];
+    let mut bufs = &mut [IoSlice::new(&buf1)][..];
+
+    // Going beyond the total length should be ok.
+    bufs = IoSlice::advance(bufs, 9);
+    assert!(bufs.is_empty());
+}
+
+/// Create a new writer that reads from at most `n_bufs` and reads
+/// `per_call` bytes (in total) per call to write.
+fn test_writer(n_bufs: usize, per_call: usize) -> TestWriter {
+    TestWriter { n_bufs, per_call, written: Vec::new() }
+}
+
+struct TestWriter {
+    n_bufs: usize,
+    per_call: usize,
+    written: Vec<u8>,
+}
+
+impl Write for TestWriter {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        self.write_vectored(&[IoSlice::new(buf)])
+    }
+
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        let mut left = self.per_call;
+        let mut written = 0;
+        for buf in bufs.iter().take(self.n_bufs) {
+            let n = min(left, buf.len());
+            self.written.extend_from_slice(&buf[0..n]);
+            left -= n;
+            written += n;
+        }
+        Ok(written)
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
+#[test]
+fn test_writer_read_from_one_buf() {
+    let mut writer = test_writer(1, 2);
+
+    assert_eq!(writer.write(&[]).unwrap(), 0);
+    assert_eq!(writer.write_vectored(&[]).unwrap(), 0);
+
+    // Read at most 2 bytes.
+    assert_eq!(writer.write(&[1, 1, 1]).unwrap(), 2);
+    let bufs = &[IoSlice::new(&[2, 2, 2])];
+    assert_eq!(writer.write_vectored(bufs).unwrap(), 2);
+
+    // Only read from first buf.
+    let bufs = &[IoSlice::new(&[3]), IoSlice::new(&[4, 4])];
+    assert_eq!(writer.write_vectored(bufs).unwrap(), 1);
+
+    assert_eq!(writer.written, &[1, 1, 2, 2, 3]);
+}
+
+#[test]
+fn test_writer_read_from_multiple_bufs() {
+    let mut writer = test_writer(3, 3);
+
+    // Read at most 3 bytes from two buffers.
+    let bufs = &[IoSlice::new(&[1]), IoSlice::new(&[2, 2, 2])];
+    assert_eq!(writer.write_vectored(bufs).unwrap(), 3);
+
+    // Read at most 3 bytes from three buffers.
+    let bufs = &[IoSlice::new(&[3]), IoSlice::new(&[4]), IoSlice::new(&[5, 5])];
+    assert_eq!(writer.write_vectored(bufs).unwrap(), 3);
+
+    assert_eq!(writer.written, &[1, 2, 2, 3, 4, 5]);
+}
+
+#[test]
+fn test_write_all_vectored() {
+    #[rustfmt::skip] // Becomes unreadable otherwise.
+    let tests: Vec<(_, &'static [u8])> = vec![
+        (vec![], &[]),
+        (vec![IoSlice::new(&[]), IoSlice::new(&[])], &[]),
+        (vec![IoSlice::new(&[1])], &[1]),
+        (vec![IoSlice::new(&[1, 2])], &[1, 2]),
+        (vec![IoSlice::new(&[1, 2, 3])], &[1, 2, 3]),
+        (vec![IoSlice::new(&[1, 2, 3, 4])], &[1, 2, 3, 4]),
+        (vec![IoSlice::new(&[1, 2, 3, 4, 5])], &[1, 2, 3, 4, 5]),
+        (vec![IoSlice::new(&[1]), IoSlice::new(&[2])], &[1, 2]),
+        (vec![IoSlice::new(&[1]), IoSlice::new(&[2, 2])], &[1, 2, 2]),
+        (vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2])], &[1, 1, 2, 2]),
+        (vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2, 2])], &[1, 1, 2, 2, 2]),
+        (vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2, 2])], &[1, 1, 2, 2, 2]),
+        (vec![IoSlice::new(&[1, 1, 1]), IoSlice::new(&[2, 2, 2])], &[1, 1, 1, 2, 2, 2]),
+        (vec![IoSlice::new(&[1, 1, 1]), IoSlice::new(&[2, 2, 2, 2])], &[1, 1, 1, 2, 2, 2, 2]),
+        (vec![IoSlice::new(&[1, 1, 1, 1]), IoSlice::new(&[2, 2, 2, 2])], &[1, 1, 1, 1, 2, 2, 2, 2]),
+        (vec![IoSlice::new(&[1]), IoSlice::new(&[2]), IoSlice::new(&[3])], &[1, 2, 3]),
+        (vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2]), IoSlice::new(&[3, 3])], &[1, 1, 2, 2, 3, 3]),
+        (vec![IoSlice::new(&[1]), IoSlice::new(&[2, 2]), IoSlice::new(&[3, 3, 3])], &[1, 2, 2, 3, 3, 3]),
+        (vec![IoSlice::new(&[1, 1, 1]), IoSlice::new(&[2, 2, 2]), IoSlice::new(&[3, 3, 3])], &[1, 1, 1, 2, 2, 2, 3, 3, 3]),
+    ];
+
+    let writer_configs = &[(1, 1), (1, 2), (1, 3), (2, 2), (2, 3), (3, 3)];
+
+    for (n_bufs, per_call) in writer_configs.iter().copied() {
+        for (mut input, wanted) in tests.clone().into_iter() {
+            let mut writer = test_writer(n_bufs, per_call);
+            assert!(writer.write_all_vectored(&mut *input).is_ok());
+            assert_eq!(&*writer.written, &*wanted);
+        }
+    }
+}
diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs
index a093b745b0c..bf289fe040e 100644
--- a/library/std/src/io/util.rs
+++ b/library/std/src/io/util.rs
@@ -1,5 +1,8 @@
 #![allow(missing_copy_implementations)]
 
+#[cfg(test)]
+mod tests;
+
 use crate::fmt;
 use crate::io::{self, BufRead, ErrorKind, Initializer, IoSlice, IoSliceMut, Read, Write};
 use crate::mem::MaybeUninit;
@@ -254,52 +257,3 @@ impl fmt::Debug for Sink {
         f.pad("Sink { .. }")
     }
 }
-
-#[cfg(test)]
-mod tests {
-    use crate::io::prelude::*;
-    use crate::io::{copy, empty, repeat, sink};
-
-    #[test]
-    fn copy_copies() {
-        let mut r = repeat(0).take(4);
-        let mut w = sink();
-        assert_eq!(copy(&mut r, &mut w).unwrap(), 4);
-
-        let mut r = repeat(0).take(1 << 17);
-        assert_eq!(copy(&mut r as &mut dyn Read, &mut w as &mut dyn Write).unwrap(), 1 << 17);
-    }
-
-    #[test]
-    fn sink_sinks() {
-        let mut s = sink();
-        assert_eq!(s.write(&[]).unwrap(), 0);
-        assert_eq!(s.write(&[0]).unwrap(), 1);
-        assert_eq!(s.write(&[0; 1024]).unwrap(), 1024);
-        assert_eq!(s.by_ref().write(&[0; 1024]).unwrap(), 1024);
-    }
-
-    #[test]
-    fn empty_reads() {
-        let mut e = empty();
-        assert_eq!(e.read(&mut []).unwrap(), 0);
-        assert_eq!(e.read(&mut [0]).unwrap(), 0);
-        assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0);
-        assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0);
-    }
-
-    #[test]
-    fn repeat_repeats() {
-        let mut r = repeat(4);
-        let mut b = [0; 1024];
-        assert_eq!(r.read(&mut b).unwrap(), 1024);
-        assert!(b.iter().all(|b| *b == 4));
-    }
-
-    #[test]
-    fn take_some_bytes() {
-        assert_eq!(repeat(4).take(100).bytes().count(), 100);
-        assert_eq!(repeat(4).take(100).bytes().next().unwrap().unwrap(), 4);
-        assert_eq!(repeat(1).take(10).chain(repeat(2).take(10)).bytes().count(), 20);
-    }
-}
diff --git a/library/std/src/io/util/tests.rs b/library/std/src/io/util/tests.rs
new file mode 100644
index 00000000000..e5e32ecb405
--- /dev/null
+++ b/library/std/src/io/util/tests.rs
@@ -0,0 +1,45 @@
+use crate::io::prelude::*;
+use crate::io::{copy, empty, repeat, sink};
+
+#[test]
+fn copy_copies() {
+    let mut r = repeat(0).take(4);
+    let mut w = sink();
+    assert_eq!(copy(&mut r, &mut w).unwrap(), 4);
+
+    let mut r = repeat(0).take(1 << 17);
+    assert_eq!(copy(&mut r as &mut dyn Read, &mut w as &mut dyn Write).unwrap(), 1 << 17);
+}
+
+#[test]
+fn sink_sinks() {
+    let mut s = sink();
+    assert_eq!(s.write(&[]).unwrap(), 0);
+    assert_eq!(s.write(&[0]).unwrap(), 1);
+    assert_eq!(s.write(&[0; 1024]).unwrap(), 1024);
+    assert_eq!(s.by_ref().write(&[0; 1024]).unwrap(), 1024);
+}
+
+#[test]
+fn empty_reads() {
+    let mut e = empty();
+    assert_eq!(e.read(&mut []).unwrap(), 0);
+    assert_eq!(e.read(&mut [0]).unwrap(), 0);
+    assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0);
+    assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0);
+}
+
+#[test]
+fn repeat_repeats() {
+    let mut r = repeat(4);
+    let mut b = [0; 1024];
+    assert_eq!(r.read(&mut b).unwrap(), 1024);
+    assert!(b.iter().all(|b| *b == 4));
+}
+
+#[test]
+fn take_some_bytes() {
+    assert_eq!(repeat(4).take(100).bytes().count(), 100);
+    assert_eq!(repeat(4).take(100).bytes().next().unwrap().unwrap(), 4);
+    assert_eq!(repeat(1).take(10).chain(repeat(2).take(10)).bytes().count(), 20);
+}