Skip to content

Commit b6296e8

Browse files
committed
Tons of testing updates, other minor changes
- Cleaned up BufWriter::seek - Updated line_vectored test - Updated line_vectored_partial_and_errors test - Added several new tests
1 parent f0a0807 commit b6296e8

File tree

1 file changed

+106
-24
lines changed

1 file changed

+106
-24
lines changed

src/libstd/io/buffered.rs

Lines changed: 106 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -751,7 +751,8 @@ impl<W: Write + Seek> Seek for BufWriter<W> {
751751
///
752752
/// Seeking always writes out the internal buffer before seeking.
753753
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
754-
self.flush_buf().and_then(|_| self.get_mut().seek(pos))
754+
self.flush_buf()?;
755+
self.get_mut().seek(pos)
755756
}
756757
}
757758

@@ -1862,12 +1863,13 @@ mod tests {
18621863
IoSlice::new(b"a"),
18631864
])
18641865
.unwrap(),
1865-
2,
1866+
1,
18661867
);
18671868
assert_eq!(a.get_ref(), b"\n");
18681869

18691870
assert_eq!(
18701871
a.write_vectored(&[
1872+
IoSlice::new(b"a"),
18711873
IoSlice::new(&[]),
18721874
IoSlice::new(b"b"),
18731875
IoSlice::new(&[]),
@@ -1876,7 +1878,7 @@ mod tests {
18761878
IoSlice::new(b"c"),
18771879
])
18781880
.unwrap(),
1879-
3,
1881+
4,
18801882
);
18811883
assert_eq!(a.get_ref(), b"\n");
18821884
a.flush().unwrap();
@@ -1893,17 +1895,21 @@ mod tests {
18931895
0,
18941896
);
18951897
assert_eq!(a.write_vectored(&[IoSlice::new(b"a\nb"),]).unwrap(), 3);
1896-
assert_eq!(a.get_ref(), b"\nabaca\n");
1898+
assert_eq!(a.get_ref(), b"\nabaca\nb");
18971899
}
18981900

18991901
#[test]
19001902
fn line_vectored_partial_and_errors() {
1903+
use crate::collections::VecDeque;
1904+
19011905
enum Call {
19021906
Write { inputs: Vec<&'static [u8]>, output: io::Result<usize> },
19031907
Flush { output: io::Result<()> },
19041908
}
1909+
1910+
#[derive(Default)]
19051911
struct Writer {
1906-
calls: Vec<Call>,
1912+
calls: VecDeque<Call>,
19071913
}
19081914

19091915
impl Write for Writer {
@@ -1912,19 +1918,23 @@ mod tests {
19121918
}
19131919

19141920
fn write_vectored(&mut self, buf: &[IoSlice<'_>]) -> io::Result<usize> {
1915-
match self.calls.pop().unwrap() {
1921+
match self.calls.pop_front().expect("unexpected call to write") {
19161922
Call::Write { inputs, output } => {
19171923
assert_eq!(inputs, buf.iter().map(|b| &**b).collect::<Vec<_>>());
19181924
output
19191925
}
1920-
_ => panic!("unexpected call to write"),
1926+
Call::Flush { .. } => panic!("unexpected call to write; expected a flush"),
19211927
}
19221928
}
19231929

1930+
fn is_write_vectored(&self) -> bool {
1931+
true
1932+
}
1933+
19241934
fn flush(&mut self) -> io::Result<()> {
1925-
match self.calls.pop().unwrap() {
1935+
match self.calls.pop_front().expect("Unexpected call to flush") {
19261936
Call::Flush { output } => output,
1927-
_ => panic!("unexpected call to flush"),
1937+
Call::Write { .. } => panic!("unexpected call to flush; expected a write"),
19281938
}
19291939
}
19301940
}
@@ -1938,27 +1948,64 @@ mod tests {
19381948
}
19391949

19401950
// partial writes keep going
1941-
let mut a = LineWriter::new(Writer { calls: Vec::new() });
1951+
let mut a = LineWriter::new(Writer::default());
19421952
a.write_vectored(&[IoSlice::new(&[]), IoSlice::new(b"abc")]).unwrap();
1943-
a.get_mut().calls.push(Call::Flush { output: Ok(()) });
1944-
a.get_mut().calls.push(Call::Write { inputs: vec![b"bcx\n"], output: Ok(4) });
1945-
a.get_mut().calls.push(Call::Write { inputs: vec![b"abcx\n"], output: Ok(1) });
1953+
1954+
a.get_mut().calls.push_back(Call::Write { inputs: vec![b"abc"], output: Ok(1) });
1955+
a.get_mut().calls.push_back(Call::Write { inputs: vec![b"bc"], output: Ok(2) });
1956+
a.get_mut().calls.push_back(Call::Write { inputs: vec![b"x", b"\n"], output: Ok(2) });
1957+
19461958
a.write_vectored(&[IoSlice::new(b"x"), IoSlice::new(b"\n")]).unwrap();
1947-
a.get_mut().calls.push(Call::Flush { output: Ok(()) });
1959+
1960+
a.get_mut().calls.push_back(Call::Flush { output: Ok(()) });
19481961
a.flush().unwrap();
19491962

19501963
// erroneous writes stop and don't write more
1951-
a.get_mut().calls.push(Call::Write { inputs: vec![b"x\n"], output: Err(err()) });
1952-
assert_eq!(a.write_vectored(&[IoSlice::new(b"x"), IoSlice::new(b"\na")]).unwrap(), 2);
1953-
a.get_mut().calls.push(Call::Flush { output: Ok(()) });
1954-
a.get_mut().calls.push(Call::Write { inputs: vec![b"x\n"], output: Ok(2) });
1964+
a.get_mut().calls.push_back(Call::Write { inputs: vec![b"x", b"\na"], output: Err(err()) });
1965+
a.get_mut().calls.push_back(Call::Flush { output: Ok(()) });
1966+
assert!(a.write_vectored(&[IoSlice::new(b"x"), IoSlice::new(b"\na")]).is_err());
19551967
a.flush().unwrap();
19561968

19571969
fn err() -> io::Error {
19581970
io::Error::new(io::ErrorKind::Other, "x")
19591971
}
19601972
}
19611973

1974+
/// Test that, in cases where vectored writing is not enabled, the
1975+
/// LineWriter uses the normal `write` call, which more-corectly handles
1976+
/// partial lines
1977+
#[test]
1978+
fn line_vectored_ignored() {
1979+
let writer = ProgrammableSink::default();
1980+
let mut writer = LineWriter::new(writer);
1981+
1982+
let content = [
1983+
IoSlice::new(b"Line 1\nLine"),
1984+
IoSlice::new(b" 2\nLine 3\nL"),
1985+
IoSlice::new(b"ine 4"),
1986+
IoSlice::new(b"\nLine 5\n"),
1987+
];
1988+
1989+
let count = writer.write_vectored(&content).unwrap();
1990+
assert_eq!(count, 11);
1991+
assert_eq!(&writer.get_ref().buffer, b"Line 1\n");
1992+
1993+
let count = writer.write_vectored(&content[1..]).unwrap();
1994+
assert_eq!(count, 11);
1995+
assert_eq!(&writer.get_ref().buffer, b"Line 1\nLine 2\nLine 3\n");
1996+
1997+
let count = writer.write_vectored(&content[2..]).unwrap();
1998+
assert_eq!(count, 5);
1999+
assert_eq!(&writer.get_ref().buffer, b"Line 1\nLine 2\nLine 3\n");
2000+
2001+
let count = writer.write_vectored(&content[3..]).unwrap();
2002+
assert_eq!(count, 8);
2003+
assert_eq!(
2004+
writer.get_ref().buffer.as_slice(),
2005+
b"Line 1\nLine 2\nLine 3\nLine 4\n Line 5".as_ref()
2006+
);
2007+
}
2008+
19622009
/// Test that, given this input:
19632010
///
19642011
/// Line 1\n
@@ -1972,7 +2019,7 @@ mod tests {
19722019
///
19732020
/// This behavior is desirable because it prevents flushing partial lines
19742021
#[test]
1975-
fn test_partial_write_buffers_line() {
2022+
fn partial_write_buffers_line() {
19762023
let writer = ProgrammableSink { accept_prefix: Some(13), ..Default::default() };
19772024
let mut writer = LineWriter::new(writer);
19782025

@@ -1992,7 +2039,7 @@ mod tests {
19922039
/// And given that the full write of lines 1 and 2 was successful
19932040
/// That data up to Line 3 is buffered
19942041
#[test]
1995-
fn test_partial_line_buffered_after_line_write() {
2042+
fn partial_line_buffered_after_line_write() {
19962043
let writer = ProgrammableSink::default();
19972044
let mut writer = LineWriter::new(writer);
19982045

@@ -2007,7 +2054,7 @@ mod tests {
20072054
/// LineBuffer's buffer (that is, without a trailing newline), that that
20082055
/// line is written to the inner writer
20092056
#[test]
2010-
fn test_long_line_flushed() {
2057+
fn long_line_flushed() {
20112058
let writer = ProgrammableSink::default();
20122059
let mut writer = LineWriter::with_capacity(5, writer);
20132060

@@ -2020,7 +2067,7 @@ mod tests {
20202067
/// and no additional writes take place. This assures the property that
20212068
/// `write` should make at-most-one attempt to write new data.
20222069
#[test]
2023-
fn test_long_tail_not_flushed() {
2070+
fn line_long_tail_not_flushed() {
20242071
let writer = ProgrammableSink::default();
20252072
let mut writer = LineWriter::with_capacity(5, writer);
20262073

@@ -2036,7 +2083,7 @@ mod tests {
20362083
/// Test that, if an attempt to pre-flush buffered data returns Ok(0),
20372084
/// this is propagated as an error.
20382085
#[test]
2039-
fn test_line_buffer_write0_error() {
2086+
fn line_buffer_write0_error() {
20402087
let writer = ProgrammableSink {
20412088
// Accept one write, then return Ok(0) on subsequent ones
20422089
max_writes: Some(1),
@@ -2060,7 +2107,7 @@ mod tests {
20602107
/// Test that, if a write returns Ok(0) after a successful pre-flush, this
20612108
/// is propogated as Ok(0)
20622109
#[test]
2063-
fn test_line_buffer_write0_normal() {
2110+
fn line_buffer_write0_normal() {
20642111
let writer = ProgrammableSink {
20652112
// Accept two writes, then return Ok(0) on subsequent ones
20662113
max_writes: Some(2),
@@ -2078,4 +2125,39 @@ mod tests {
20782125
assert_eq!(writer.write(b" Line End\n").unwrap(), 0);
20792126
assert_eq!(&writer.get_ref().buffer, b"Line 1\nPartial");
20802127
}
2128+
2129+
/// LineWriter has a custom `write_all`; make sure it works correctly
2130+
#[test]
2131+
fn line_write_all() {
2132+
let writer = ProgrammableSink {
2133+
// Only write 5 bytes at a time
2134+
accept_prefix: Some(5),
2135+
..Default::default()
2136+
};
2137+
let mut writer = LineWriter::new(writer);
2138+
2139+
writer.write_all(b"Line 1\nLine 2\nLine 3\nLine 4\nPartial").unwrap();
2140+
assert_eq!(&writer.get_ref().buffer, b"Line 1\nLine 2\nLine 3\nLine 4\n");
2141+
writer.write_all(b" Line 5\n").unwrap();
2142+
assert_eq!(
2143+
writer.get_ref().buffer.as_slice(),
2144+
b"Line 1\nLine 2\nLine 3\nLine 4\nPartial Line 5\n".as_ref(),
2145+
);
2146+
}
2147+
2148+
#[test]
2149+
fn line_write_all_error() {
2150+
let writer = ProgrammableSink {
2151+
// Only accept up to 3 writes of up to 5 bytes each
2152+
accept_prefix: Some(5),
2153+
max_writes: Some(3),
2154+
..Default::default()
2155+
};
2156+
2157+
let mut writer = LineWriter::new(writer);
2158+
let res = writer.write_all(b"Line 1\nLine 2\nLine 3\nLine 4\nPartial");
2159+
assert!(res.is_err());
2160+
// An error from write_all leaves everything in an indeterminate state,
2161+
// so there's nothing else to test here
2162+
}
20812163
}

0 commit comments

Comments
 (0)