From 862d785220a43df252d43b3bc0d2b5823aa0c676 Mon Sep 17 00:00:00 2001 From: Anas Elgarhy Date: Thu, 13 Oct 2022 17:11:50 +0200 Subject: [PATCH] =?UTF-8?q?Create=20more=20tests=20yooo=20=F0=9F=92=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/bf_interpreter/cell.rs | 167 ++++++++++++++++++++++++++++-- src/bf_interpreter/interpreter.rs | 34 +++--- src/main.rs | 4 +- src/repl.rs | 40 +++---- 4 files changed, 193 insertions(+), 52 deletions(-) diff --git a/src/bf_interpreter/cell.rs b/src/bf_interpreter/cell.rs index d9eff31..2914315 100644 --- a/src/bf_interpreter/cell.rs +++ b/src/bf_interpreter/cell.rs @@ -8,21 +8,14 @@ pub enum Cell { } impl Cell { - pub fn set_value_utf8(&mut self, ch: char) { - match self { - Cell::Byte(_) => {} - Cell::Utf8(p) => { - *p = ch as u32; - } - } - } - pub fn set_value(&mut self, ch: char) { match self { Cell::Byte(p) => { *p = ch as u8; } - Cell::Utf8(_) => {} + Cell::Utf8(p) => { + *p = ch as u32; + } } } } @@ -36,6 +29,8 @@ impl Cell { } } + #[allow(dead_code)] + /// For testing purposes pub fn new(value: u32, future: &Vec) -> Self { if future.contains(&Feature::AllowUtf8) { Cell::Utf8(value) @@ -107,7 +102,7 @@ impl Cell { pub fn max_value(&self) -> u32 { match self { Self::Byte(_) => u8::MAX as u32, - Self::Utf8(_) => u32::MAX, + Self::Utf8(_) => 1114111, } } @@ -132,4 +127,154 @@ impl std::fmt::Display for Cell { Self::Utf8(value) => write!(f, "{}", value), } } +} + +#[cfg(test)] +mod tests { + use super::*; + use pretty_assertions::assert_eq; + + #[test] + fn test_increment_u8_no_revers() { + let mut cell = Cell::default_cell(&vec![]); + cell.increment(true).unwrap(); + assert_eq!(cell, Cell::Byte(1)); + + for _ in 0..254 { + cell.increment(true).unwrap(); + } + assert_eq!(cell, Cell::Byte(255)); + + assert_eq!(cell.increment(true).unwrap_err(), InterpreterErrorKind::ValueOutOfBounds.to_error()); + assert_eq!(cell, Cell::Byte(255)); + } + + #[test] + fn test_increment_u32_no_revers() { + let mut cell = Cell::default_cell(&vec![Feature::AllowUtf8]); + cell.increment(true).unwrap(); + assert_eq!(cell, Cell::Utf8(1)); + + for _ in 0..1114110 { + cell.increment(true).unwrap(); + } + assert_eq!(cell, Cell::Utf8(1114111)); + + assert_eq!(cell.increment(true).unwrap_err(), InterpreterErrorKind::ValueOutOfBounds.to_error()); + assert_eq!(cell, Cell::Utf8(1114111)); + } + + #[test] + fn test_increment_u8_revers() { + let mut cell = Cell::default_cell(&vec![]); + cell.increment(false).unwrap(); + assert_eq!(cell, Cell::Byte(1)); + + for _ in 0..254 { + cell.increment(false).unwrap(); + } + assert_eq!(cell, Cell::Byte(255)); + + cell.increment(false).unwrap(); + assert_eq!(cell, Cell::Byte(0)); + } + + #[test] + fn test_increment_u32_revers() { + let mut cell = Cell::default_cell(&vec![Feature::AllowUtf8]); + cell.increment(false).unwrap(); + assert_eq!(cell, Cell::Utf8(1)); + + for _ in 0..1114110 { + cell.increment(false).unwrap(); + } + assert_eq!(cell, Cell::Utf8(1114111)); + + cell.increment(false).unwrap(); + assert_eq!(cell, Cell::Utf8(0)); + } + + #[test] + fn test_decrement_u8_no_revers() { + let mut cell = Cell::new(255, &vec![]); + cell.decrement(true).unwrap(); + assert_eq!(cell, Cell::Byte(254)); + + for _ in 0..254 { + cell.decrement(true).unwrap(); + } + assert_eq!(cell, Cell::Byte(0)); + + assert_eq!(cell.decrement(true).unwrap_err(), InterpreterErrorKind::ValueOutOfBounds.to_error()); + assert_eq!(cell, Cell::Byte(0)); + } + + #[test] + fn test_decrement_u32_no_revers() { + let mut cell = Cell::new(1114111, &vec![Feature::AllowUtf8]); + cell.decrement(true).unwrap(); + assert_eq!(cell, Cell::Utf8(1114110)); + + for _ in 0..1114110 { + cell.decrement(true).unwrap(); + } + assert_eq!(cell, Cell::Utf8(0)); + + assert_eq!(cell.decrement(true).unwrap_err(), InterpreterErrorKind::ValueOutOfBounds.to_error()); + assert_eq!(cell, Cell::Utf8(0)); + } + + #[test] + fn test_decrement_u8_revers() { + let mut cell = Cell::new(0, &vec![]); + cell.decrement(false).unwrap(); + assert_eq!(cell, Cell::Byte(255)); + + for _ in 0..254 { + cell.decrement(false).unwrap(); + } + assert_eq!(cell, Cell::Byte(1)); + + cell.decrement(false).unwrap(); + assert_eq!(cell, Cell::Byte(0)); + } + + #[test] + fn test_decrement_u32_revers() { + let mut cell = Cell::new(0, &vec![Feature::AllowUtf8]); + cell.decrement(false).unwrap(); + assert_eq!(cell, Cell::Utf8(1114111)); + + for _ in 0..1114110 { + cell.decrement(false).unwrap(); + } + assert_eq!(cell, Cell::Utf8(1)); + + cell.decrement(false).unwrap(); + assert_eq!(cell, Cell::Utf8(0)); + } + + #[test] + fn test_to_char() { + let cell = Cell::new(65, &vec![]); + assert_eq!(cell.to_char().unwrap(), 'A'); + + let cell = Cell::new(129408, &vec![Feature::AllowUtf8]); + assert_eq!(cell.to_char().unwrap(), '🦀'); + + let cell = Cell::new(129392, &vec![Feature::AllowUtf8]); + assert_eq!(cell.to_char().unwrap(), '🥰'); + } + + #[test] + fn test_set_value() { + let mut cell = Cell::default_cell(&vec![]); + cell.set_value('A'); + assert_eq!(cell, Cell::Byte(65)); + + let mut cell = Cell::default_cell(&vec![Feature::AllowUtf8]); + cell.set_value('🦀'); + assert_eq!(cell, Cell::Utf8(129408)); + } + } \ No newline at end of file diff --git a/src/bf_interpreter/interpreter.rs b/src/bf_interpreter/interpreter.rs index eb7a649..f8e9112 100644 --- a/src/bf_interpreter/interpreter.rs +++ b/src/bf_interpreter/interpreter.rs @@ -10,14 +10,14 @@ pub struct Interpreter { pub bf_commands: Vec, brackets: Vec, pub features: Vec, - term: console::Term, + pub term: console::Term, } impl Interpreter { pub fn new( array_size: usize, features: Vec, - term: &console::Term, + term: console::Term, ) -> Self { Self { cells: vec![Cell::default_cell(&features); array_size], @@ -25,7 +25,7 @@ impl Interpreter { bf_commands: vec![], brackets: Vec::new(), features, - term: term.clone(), + term, } } @@ -126,11 +126,7 @@ impl Interpreter { trace!("Input value"); match self.term.read_char() { Ok(ch) => { - if self.features.contains(&arguments::Feature::AllowUtf8) { - self.cells[self.pointer].set_value_utf8(ch); - } else { self.cells[self.pointer].set_value(ch); - } print!("{}", ch); match std::io::stdout().flush() { Ok(_) => Ok(()), @@ -211,14 +207,14 @@ impl BfCommand { #[cfg(test)] mod tests { + use console::Term; use super::*; use crate::utils; use pretty_assertions::assert_eq; // for testing only #[test] fn print_h_combine_repl() { - let mut interpreter = Interpreter::new(30000, vec![], - &console::Term::stdout()); + let mut interpreter = Interpreter::new(30000, vec![], Term::stdout()); assert_eq!( interpreter.run(String::from(">+++++++++[<++++ ++++>-]<.")), @@ -231,7 +227,7 @@ mod tests { #[test] fn print_h_repl() { let mut interpreter = Interpreter::new(30000, vec![], - &console::Term::stdout()); + Term::stdout()); assert_eq!(interpreter.run(String::from(">+++++++++")), Ok(0)); assert_eq!(interpreter.run(String::from("[<++++ ++++>-]<.")), Ok(0)); @@ -242,7 +238,7 @@ mod tests { #[test] fn nested_loop_level_1_combine() { let mut interpreter = Interpreter::new(5, vec![], - &console::Term::stdout()); + Term::stdout()); assert_eq!(interpreter.run(String::from("++[>++[>+<-]<-]")), Ok(0)); assert_eq!(interpreter.cells[2], Cell::new(4, &vec![])); @@ -253,7 +249,7 @@ mod tests { #[test] fn execute_hello_world_from_file() { let mut interpreter = Interpreter::new(30000, vec![], - &console::Term::stdout()); + Term::stdout()); println!(); @@ -268,7 +264,7 @@ mod tests { #[test] fn execute_print_hi_from_file() { let mut interpreter = Interpreter::new(30000, vec![], - &console::Term::stdout()); + Term::stdout()); println!(); @@ -283,7 +279,7 @@ mod tests { #[test] fn execute_print_hi_yooo_from_file() { let mut interpreter = Interpreter::new(30000, vec![], - &console::Term::stdout()); + Term::stdout()); println!(); @@ -298,7 +294,7 @@ mod tests { #[test] fn execute_print_my_first_name_from_formatted_file() { let mut interpreter = Interpreter::new(30000, vec![], - &console::Term::stdout()); + Term::stdout()); println!(); @@ -313,7 +309,7 @@ mod tests { #[test] fn execute_print_my_first_name_from_file() { let mut interpreter = Interpreter::new(30000, vec![], - &console::Term::stdout()); + Term::stdout()); println!(); @@ -336,7 +332,7 @@ mod tests { #[test] fn execute_print_my_first_name_and_last_name_from_formatted_file() { let mut interpreter = Interpreter::new(30000, vec![], - &console::Term::stdout()); + Term::stdout()); println!(); @@ -351,7 +347,7 @@ mod tests { #[test] fn execute_print_my_first_name_and_last_name_from_file() { let mut interpreter = Interpreter::new(30000, vec![], - &console::Term::stdout()); + Term::stdout()); println!(); @@ -366,7 +362,7 @@ mod tests { #[test] fn reset() { let mut interpreter = Interpreter::new(30000, vec![], - &console::Term::stdout()); + Term::stdout()); assert_eq!(interpreter.run(String::from(">++++")), Ok(0)); diff --git a/src/main.rs b/src/main.rs index 833e970..d666817 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,7 +25,7 @@ fn main() { let mut interpreter = Interpreter::new(args.array_size, args.features.unwrap_or_else(|| vec![]), - &term); + term); match args.source { Some(source) => { @@ -60,6 +60,6 @@ fn main() { } } } - None => repl::start(interpreter, term), + None => repl::start(interpreter), } } diff --git a/src/repl.rs b/src/repl.rs index d705a64..4f3e632 100644 --- a/src/repl.rs +++ b/src/repl.rs @@ -5,7 +5,7 @@ use console::{Term, Key}; struct Repl { pub interpreter: Interpreter, - term: console::Term, + term: Term, history: Vec, loop_body: String, loop_depth: usize, @@ -16,10 +16,10 @@ const HISTORY_FILE: &str = "bf-interpreter-history.bfr"; const COMMAND_PREFIX: &str = "!"; impl Repl { - pub fn new(interpreter: Interpreter, term: Term) -> Repl { + pub fn new(interpreter: Interpreter) -> Repl { Repl { + term: interpreter.term.clone(), interpreter, - term, history: Vec::new(), loop_body: String::new(), loop_depth: 0, @@ -299,7 +299,7 @@ impl Repl { /// Run the REPL /// # Arguments /// * `interpreter` - The interpreter to use -pub fn start(interpreter: Interpreter, term: Term) { +pub fn start(interpreter: Interpreter) { info!("Entering REPL mode"); println!( "{}\n\ @@ -317,7 +317,7 @@ pub fn start(interpreter: Interpreter, term: Term) { (COMMAND_PREFIX.to_string() + "help").bold().green(), ); - match Repl::new(interpreter, term).run() { + match Repl::new(interpreter).run() { Ok(_) => { info!("Successfully ran REPL"); } @@ -336,10 +336,10 @@ mod tests { #[test] fn nested_loop_level_1() { - let mut term = Term::stdout(); - let interpreter = Interpreter::new(4, vec![], &mut term); + let term = Term::stdout(); + let interpreter = Interpreter::new(4, vec![], term); - let mut repl = Repl::new(interpreter, term); + let mut repl = Repl::new(interpreter); repl.process("++".to_string()); repl.process("[>++".to_string()); @@ -355,10 +355,10 @@ mod tests { #[test] fn nested_loop_level_2() { - let mut term = console::Term::stdout(); - let interpreter = Interpreter::new(4, vec![], &mut term); + let term = Term::stdout(); + let interpreter = Interpreter::new(4, vec![], term); - let mut repl = Repl::new(interpreter, term); + let mut repl = Repl::new(interpreter); repl.process("++".to_string()); repl.process("[>++".to_string()); @@ -377,10 +377,10 @@ mod tests { #[test] fn print_my_first_name() { - let mut term = console::Term::stdout(); - let interpreter = Interpreter::new(10, vec![], &mut term); + let term = Term::stdout(); + let interpreter = Interpreter::new(10, vec![], term); - let mut repl = Repl::new(interpreter, term); + let mut repl = Repl::new(interpreter); let code = "++++ ++++ 8 [ @@ -449,10 +449,10 @@ mod tests { #[test] fn print_my_first_name_in_one_command() { - let mut term = Term::stdout(); - let interpreter = Interpreter::new(10, vec![], &mut term); + let term = Term::stdout(); + let interpreter = Interpreter::new(10, vec![], term); - let mut repl = Repl::new(interpreter, term); + let mut repl = Repl::new(interpreter); let code = "++++++++[>++++[>++>+++>++++>+<<<<-]>>>>>>++[<<<->>>-]<<<<<<<-]>>+.\ <<++++[>+++[>+++<-]>++<<-]>>+.<<+++[>+++[>-<-]>-<<-]>>-.<<++++++[>>+++<<-]>>." @@ -470,10 +470,10 @@ mod tests { #[test] fn print_hello_world() { - let mut term = console::Term::stdout(); - let interpreter = Interpreter::new(10, vec![], &mut term); + let term = Term::stdout(); + let interpreter = Interpreter::new(10, vec![], term); - let mut repl = Repl::new(interpreter, term); + let mut repl = Repl::new(interpreter); let _ = "[ This program prints \"Hello World!\" and a newline to the screen, its length is 106 active command characters. [It is not the shortest.]