Add Window tests and fixes

This commit is contained in:
altugbakan 2023-03-30 19:54:46 +03:00 committed by Altuğ Bakan
parent 361d077d1b
commit ef28c2585d
3 changed files with 79 additions and 2 deletions

1
.gitignore vendored
View file

@ -1 +1,2 @@
/target /target
/tmp

View file

@ -177,7 +177,7 @@ impl TransferOption {
/// ```rust /// ```rust
/// use tftpd::OptionType; /// use tftpd::OptionType;
/// ///
/// assert_eq!(OptionType::BlockSize, OptionType::from_str("blksize").unwrap()); /// assert_eq!(OptionType::BlockSize, "blksize".parse().unwrap());
/// assert_eq!("tsize", OptionType::TransferSize.as_str()); /// assert_eq!("tsize", OptionType::TransferSize.as_str());
/// ``` /// ```
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]

View file

@ -1,5 +1,23 @@
use std::{collections::VecDeque, error::Error, fs::File, io::Read}; use std::{collections::VecDeque, error::Error, fs::File, io::Read};
/// Window `struct` is used to store chunks of data from a file.
/// It is used to store the data that is being sent or received for
/// Windowsize option.
///
/// # Example
/// ```rust
/// use std::{fs::{self, OpenOptions, File}, io::Write};
/// use tftpd::Window;
///
/// let mut file = File::create("test.txt").unwrap();
/// file.write_all(b"Hello, world!").unwrap();
/// file.flush().unwrap();
///
/// let file = File::open("test.txt").unwrap();
/// let mut window = Window::new(5, 512, file);
/// window.fill().unwrap();
/// fs::remove_file("test.txt").unwrap();
/// ```
pub struct Window { pub struct Window {
elements: VecDeque<Vec<u8>>, elements: VecDeque<Vec<u8>>,
size: usize, size: usize,
@ -8,6 +26,7 @@ pub struct Window {
} }
impl Window { impl Window {
/// Creates a new `Window` with the supplied size and chunk size.
pub fn new(size: usize, chunk_size: usize, file: File) -> Window { pub fn new(size: usize, chunk_size: usize, file: File) -> Window {
Window { Window {
elements: VecDeque::new(), elements: VecDeque::new(),
@ -17,20 +36,25 @@ impl Window {
} }
} }
/// Fills the `Window` with chunks of data from the file.
pub fn fill(&mut self) -> Result<(), Box<dyn Error>> { pub fn fill(&mut self) -> Result<(), Box<dyn Error>> {
for _ in self.elements.len()..self.size { for _ in self.elements.len()..self.size {
let mut chunk = vec![0; self.chunk_size]; let mut chunk = vec![0; self.chunk_size];
let size = self.file.read(&mut chunk)?; let size = self.file.read(&mut chunk)?;
self.elements.push_back(chunk);
if size != self.chunk_size { if size != self.chunk_size {
chunk.truncate(size);
self.elements.push_back(chunk);
break; break;
} }
self.elements.push_back(chunk);
} }
Ok(()) Ok(())
} }
/// Removes the first `amount` of elements from the `Window`.
pub fn remove(&mut self, amount: usize) -> Result<(), Box<dyn Error>> { pub fn remove(&mut self, amount: usize) -> Result<(), Box<dyn Error>> {
if amount > self.elements.len() { if amount > self.elements.len() {
return Err("amount cannot be larger than size".into()); return Err("amount cannot be larger than size".into());
@ -41,3 +65,55 @@ impl Window {
Ok(()) Ok(())
} }
} }
#[cfg(test)]
mod tests {
use super::*;
use std::{fs, io::Write};
#[test]
fn fills_and_removes_from_window() {
let file = initialize();
let mut window = Window::new(2, 5, file);
window.fill().unwrap();
assert_eq!(window.elements.len(), 2);
assert_eq!(window.elements[0], b"Hello"[..]);
assert_eq!(window.elements[1], b", wor"[..]);
window.remove(1).unwrap();
assert_eq!(window.elements.len(), 1);
assert_eq!(window.elements[0], b", wor"[..]);
window.fill().unwrap();
assert_eq!(window.elements.len(), 2);
assert_eq!(window.elements[0], b", wor"[..]);
assert_eq!(window.elements[1], b"ld!"[..]);
clean();
}
fn initialize() -> File {
let dir_name = "tmp";
let file_name = "tmp/test.txt";
if fs::metadata(dir_name).is_err() {
fs::create_dir(dir_name).unwrap();
}
if File::open(file_name).is_ok() {
fs::remove_file(file_name).unwrap();
}
let mut file = File::create(file_name).unwrap();
file.write_all(b"Hello, world!").unwrap();
file.flush().unwrap();
File::open(file_name).unwrap()
}
fn clean() {
fs::remove_file("tmp/test.txt").unwrap();
fs::remove_dir("tmp").unwrap();
}
}