use super::reader::Reader;
use crate::io::{self as ggio, ByteReader};
use std::io::Read;
#[test]
fn test_reader() {
let mut r = Reader::new("0123456789".as_bytes());
struct Test {
off: i64,
seek: ggio::Seek,
n: usize,
want: &'static [u8],
wantpos: u64,
readerr: Option<&'static str>,
seekerr: Option<&'static str>,
}
let tests = [
Test {
seek: ggio::Seek::Start,
off: 0,
n: 20,
want: "0123456789".as_bytes(),
wantpos: 0,
readerr: None,
seekerr: None,
},
Test {
seek: ggio::Seek::Start,
off: 1,
n: 1,
want: "1".as_bytes(),
wantpos: 0,
readerr: None,
seekerr: None,
},
Test {
seek: ggio::Seek::Current,
off: 1,
wantpos: 3,
n: 2,
want: "34".as_bytes(),
readerr: None,
seekerr: None,
},
Test {
seek: ggio::Seek::Start,
off: -1,
n: 0,
want: &[],
wantpos: 0,
readerr: None,
seekerr: Some("bytes::Reader::seek: negative position"),
},
Test {
seek: ggio::Seek::Start,
off: 1 << 33,
wantpos: 1 << 33,
n: 0,
want: &[],
readerr: None,
seekerr: None,
},
Test {
seek: ggio::Seek::Current,
off: 1,
wantpos: (1 << 33) + 1,
n: 0,
want: &[],
readerr: None,
seekerr: None,
},
Test {
seek: ggio::Seek::Start,
n: 5,
want: "01234".as_bytes(),
off: 0,
wantpos: 0,
readerr: None,
seekerr: None,
},
Test {
seek: ggio::Seek::Current,
n: 5,
want: "56789".as_bytes(),
off: 0,
wantpos: 0,
readerr: None,
seekerr: None,
},
Test {
seek: ggio::Seek::End,
off: -1,
n: 1,
wantpos: 9,
want: "9".as_bytes(),
readerr: None,
seekerr: None,
},
];
for (i, tt) in tests.iter().enumerate() {
let res = r.seek(tt.off, tt.seek);
if res.is_ok() && tt.seekerr.is_some() {
panic!("{}. want seek error {}", i, tt.seekerr.as_ref().unwrap());
}
match res {
Err(err) => {
let errstr = err.to_string();
assert_eq!(
tt.seekerr.as_ref().unwrap(),
&errstr,
"{}. seek error = '{}'; want '{}'",
i,
errstr,
tt.seekerr.as_ref().unwrap()
);
}
Ok(pos) => {
if tt.wantpos != 0 {
assert_eq!(tt.wantpos, pos, "{}. pos = {}, want {}", i, pos, tt.wantpos);
}
}
}
let mut buf = vec![0; tt.n];
let res = r.read(&mut buf);
if res.is_ok() {
if tt.readerr.is_some() {
panic!("{}. read = no error; want {:?}", i, tt.readerr);
}
} else if tt.readerr.is_none() {
panic!("{}. read = {:?}; want = no error", i, res);
} else {
let errstr = res.as_ref().unwrap_err().to_string();
assert_eq!(
tt.readerr.as_ref().unwrap(),
&errstr,
"{}. read error = '{}'; want '{}'",
i,
errstr,
tt.readerr.as_ref().unwrap()
);
}
let n = res.unwrap();
let got = &buf[..n];
assert_eq!(tt.want, got, "{}. got {:?}; want {:?}", i, got, tt.want);
}
}
#[test]
fn test_read_after_big_seek() {
let mut r = Reader::new("0123456789".as_bytes());
r.seek((1 << 31) + 5, ggio::Seek::Start).unwrap();
let mut buf = [0; 10];
let res = r.read(&mut buf);
assert!(res.is_ok() && res.unwrap() == 0);
}
#[test]
fn test_reader_at() {
let mut r = Reader::new("0123456789".as_bytes());
struct Test {
off: u64,
n: usize,
want: &'static [u8],
wanterr: Option<&'static str>,
}
let tests = &[
Test {
off: 0,
n: 10,
want: "0123456789".as_bytes(),
wanterr: None,
},
Test {
off: 1,
n: 10,
want: "123456789".as_bytes(),
wanterr: None,
},
Test {
off: 1,
n: 9,
want: "123456789".as_bytes(),
wanterr: None,
},
Test {
off: 11,
n: 10,
want: "".as_bytes(),
wanterr: None,
},
Test {
off: 0,
n: 0,
want: "".as_bytes(),
wanterr: None,
},
];
for (i, tt) in tests.iter().enumerate() {
let mut b = vec![0; tt.n];
let res = r.read_at(&mut b, tt.off);
match res {
Ok(rn) => {
let got = &b[..rn];
assert_eq!(tt.want, got, "{}. got {:?}; want {:?}", i, got, tt.want);
}
Err(err) => {
let got = err.to_string();
let wanterr = tt.wanterr.unwrap();
assert_eq!(
wanterr, got,
"{}. got error = '{:?}'; want '{:?}'",
i, got, wanterr
);
}
}
}
}
#[test]
fn test_reader_len() {
let data = "hello world";
let mut r = Reader::new(data.as_bytes());
let want = 11;
let got = r.len();
assert_eq!(want, got, "r.len(): got {}, want {}", got, want);
let mut buf = [0; 10];
let res = r.read(&mut buf);
assert!(res.is_ok() && res.unwrap() == 10);
let want = 1;
let got = r.len();
assert_eq!(want, got, "r.len(): got {}, want {}", got, want);
let mut buf = [0; 1];
let res = r.read(&mut buf);
assert!(res.is_ok() && res.unwrap() == 1);
let want = 0;
let got = r.len();
assert_eq!(want, got, "r.len(): got {}, want {}", got, want);
}
#[test]
fn test_reader_len_size() {
let mut r = Reader::new("abc".as_bytes());
ggio::copy_n(&mut ggio::Discard::new(), &mut r, 1);
assert_eq!(2, r.len(), "len = {}; want 2", r.len());
assert_eq!(3, r.size(), "size = {}; want 3", r.size());
}
#[test]
fn test_reader_zero() {
let l = Reader::new(&[]).len();
assert_eq!(0, l, "len: got {}, want 0", l);
let mut buf = [];
let res = Reader::new(&[]).read(&mut buf);
assert!(res.is_ok() && res.unwrap() == 0);
let res = Reader::new(&[]).read_at(&mut buf, 11);
assert!(res.is_ok_and(|x| x == 0));
let res = Reader::new(&[]).read_byte();
assert!(res.is_err());
assert!(res.err().unwrap().kind() == std::io::ErrorKind::UnexpectedEof);
let offset = Reader::new(&[]).seek(11, ggio::Seek::Start).unwrap();
assert!(offset == 11, "Seek: got {}; want 11", offset);
let s = Reader::new(&[]).size();
assert_eq!(0, s, "size: got {}, want 0", s);
assert!(
Reader::new(&[]).unread_byte().is_err(),
"unread_byte: got nil, want error"
);
let res = Reader::new(&[]).write_to(&mut ggio::Discard::new());
assert!(
res.as_ref().is_ok_and(|x| *x == 0),
"write_to: got {:?}; want 0, nil",
res
);
}
#[test]
fn test_reader_std_io_read() {
let mut r = Reader::new(b"hello".as_slice());
let mut buf = [0; 2];
assert_eq!(2, std::io::Read::read(&mut r, &mut buf).unwrap());
assert_eq!(b"he", &buf);
assert_eq!(2, std::io::Read::read(&mut r, &mut buf).unwrap());
assert_eq!(b"ll", &buf);
assert_eq!(1, std::io::Read::read(&mut r, &mut buf).unwrap());
assert_eq!(b"o", &buf[..1]);
}