#[cfg(test)]
mod tests {
use std::io::Write;
use tempfile::NamedTempFile;
use tokio::fs::File;
use crate::source::file::seek::from_end;
async fn open(body: &[u8]) -> (File, NamedTempFile) {
let mut tmp = NamedTempFile::new().unwrap();
tmp.write_all(body).unwrap();
tmp.flush().unwrap();
let file = File::open(tmp.path()).await.unwrap();
(file, tmp)
}
#[tokio::test]
async fn zero_lines_seeks_to_end() {
let (mut f, _g) = open(b"alpha\nbeta\ngamma\n").await;
let off = from_end(&mut f, 0).await.unwrap();
assert_eq!(off, 17);
}
#[tokio::test]
async fn single_line_from_end() {
let (mut f, _g) = open(b"alpha\nbeta\ngamma\n").await;
let off = from_end(&mut f, 1).await.unwrap();
assert_eq!(off, 11);
}
#[tokio::test]
async fn more_lines_than_file_has_returns_zero() {
let (mut f, _g) = open(b"alpha\nbeta\n").await;
let off = from_end(&mut f, 100).await.unwrap();
assert_eq!(off, 0);
}
#[tokio::test]
async fn no_trailing_newline_works() {
let (mut f, _g) = open(b"alpha\nbeta\ngamma").await;
let off = from_end(&mut f, 1).await.unwrap();
assert_eq!(off, 11);
}
#[tokio::test]
async fn across_chunk_boundaries() {
let mut body = Vec::new();
for i in 0..5000 {
body.extend_from_slice(format!("line {}\n", i).as_bytes());
}
let (mut f, _g) = open(&body).await;
let off = from_end(&mut f, 1).await.unwrap();
let tail = &body[off as usize..];
assert_eq!(tail, b"line 4999\n");
}
#[tokio::test]
async fn empty_file_returns_zero() {
let (mut f, _g) = open(b"").await;
let off = from_end(&mut f, 5).await.unwrap();
assert_eq!(off, 0);
}
#[tokio::test]
async fn single_byte_non_newline() {
let (mut f, _g) = open(b"x").await;
let off = from_end(&mut f, 1).await.unwrap();
assert_eq!(off, 0);
}
}