From e09b82bdf7fff3a17be1ea0277f49a29bf8a3f25 Mon Sep 17 00:00:00 2001 From: Roshan Patel Date: Sun, 7 Apr 2024 02:16:17 -0400 Subject: [PATCH] Move tests to subdirectory, fmt code. --- Cargo.toml | 4 +- src/backend.rs | 136 +++++++-------------------------------- src/main.rs | 11 +++- src/parser.rs | 25 +++---- src/tests/integration.rs | 3 + src/tests/unit_tests.rs | 87 +++++++++++++++++++++++++ 6 files changed, 139 insertions(+), 127 deletions(-) create mode 100644 src/tests/integration.rs create mode 100644 src/tests/unit_tests.rs diff --git a/Cargo.toml b/Cargo.toml index 12cd028..749a81e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,9 +2,9 @@ name = "sql_engine" version = "0.1.0" edition = "2021" +authors = ["Roshan Patel"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -scan_fmt = "0.2.6" - +scan_fmt = "0.2.6" \ No newline at end of file diff --git a/src/backend.rs b/src/backend.rs index 481c6af..559da34 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -1,16 +1,16 @@ +use crate::parser::*; use std::io; use std::process::exit; -use crate::parser::*; #[derive(PartialEq, Debug, Default)] pub enum ExecuteResult { SUCCESS, #[default] - TABLE_FULL + TABLE_FULL, } pub struct Table { - pub data: Vec + pub data: Vec, } impl Table { @@ -19,12 +19,12 @@ impl Table { } } -pub fn entrypoint() -{ +pub fn entrypoint() { let stdin = io::stdin(); // binding a handle. let mut table = Table::new(); - loop // same as while(true) + loop + // same as while(true) { let mut input = String::new(); @@ -33,11 +33,11 @@ pub fn entrypoint() input = input.trim().to_string(); // remove trailing newline. // Is a command - if input.starts_with('.') - { - match execute_command(&input) - { - MetaCommandResult::SUCCESS => { continue; } // Executed command, get next input. + if input.starts_with('.') { + match execute_command(&input) { + MetaCommandResult::SUCCESS => { + continue; + } // Executed command, get next input. MetaCommandResult::UNRECOGNIZED => { println!("Unrecognized command: {}", input); continue; // skip this iteration of our IO loop. @@ -47,9 +47,10 @@ pub fn entrypoint() let mut statement = Statement::default(); - match prepare_statement(&input, &mut statement) - { - PrepareResult::SUCCESS => { println!("Successfully prepared statement...") } + match prepare_statement(&input, &mut statement) { + PrepareResult::SUCCESS => { + println!("Successfully prepared statement...") + } PrepareResult::UNRECOGNIZED => { println!("Unrecognized keyword at start of {}", input); continue; @@ -61,26 +62,25 @@ pub fn entrypoint() } match execute_statement(statement, &mut table) { - ExecuteResult::SUCCESS => { println!("Successfully executed...") } - ExecuteResult::TABLE_FULL => { println!("Table is full...") } + ExecuteResult::SUCCESS => { + println!("Successfully executed...") + } + ExecuteResult::TABLE_FULL => { + println!("Table is full...") + } } } } -pub fn execute_command(cmd: &String) -> MetaCommandResult -{ - if cmd == ".exit" - { +pub fn execute_command(cmd: &String) -> MetaCommandResult { + if cmd == ".exit" { exit(0); - } - else - { + } else { return MetaCommandResult::UNRECOGNIZED; } } -fn execute_statement(statement: Statement, tb: &mut Table) -> ExecuteResult -{ +fn execute_statement(statement: Statement, tb: &mut Table) -> ExecuteResult { match statement.cmd { StatementType::INSERT => { println!("Performing an insert..."); @@ -100,7 +100,6 @@ fn execute_insert(statement: Statement, table: &mut Table) -> ExecuteResult { } fn execute_select(statement: Statement, table: &mut Table) -> ExecuteResult { - for row in table.data.iter() { if row.id == statement.row_instance.id { println!("Found data: {:?}", row); @@ -108,88 +107,3 @@ fn execute_select(statement: Statement, table: &mut Table) -> ExecuteResult { } ExecuteResult::SUCCESS } - -#[cfg(test)] -mod backend_tests { - use crate::backend::*; - use crate::parser::*; - - // Testing whether unrecognized commands are rejected. - #[test] - fn execute_command_unrecognized() { - let cmd = String::from(".dummy"); - let out = execute_command(&cmd); - assert_eq!(out, MetaCommandResult::UNRECOGNIZED); - } - - // Testing whether the enum is set properly. - #[test] - fn prepare_statement_set_insert() { - let mut out_statement = Statement::default(); - let cmd = String::from("insert"); - prepare_statement(&cmd, &mut out_statement); - assert_eq!(out_statement.cmd, StatementType::INSERT); - } - - // Testing whether the enum is set properly. - #[test] - fn prepare_statement_set_select() { - let mut out_statement = Statement::default(); - let cmd = String::from("select"); - prepare_statement(&cmd, &mut out_statement); - assert_eq!(out_statement.cmd, StatementType::SELECT); - } - - // Testing whether the output result is correct. - #[test] - fn prepare_statement_out_success() { - let mut out_statement = Statement::default(); - let cmd = String::from("insert 10 monkeylover ape@gmail.com"); - let out_result = prepare_statement(&cmd, &mut out_statement); - assert_eq!(out_result, PrepareResult::SUCCESS); - } - - // Testing whether the output result handles bad commands. - #[test] - fn prepare_statement_out_failure() { - let mut out_statement = Statement::default(); - let cmd = String::from("dummy"); - let out_result = prepare_statement(&cmd, &mut out_statement); - assert_eq!(out_result, PrepareResult::UNRECOGNIZED); - } - - // Testing whether the insert syntax error is handled. - #[test] - fn prepare_statement_out_syntax_error() { - let mut out_statement = Statement::default(); - let cmd = String::from("insert"); - let out_result = prepare_statement(&cmd, &mut out_statement); - assert_eq!(out_result, PrepareResult::SYNTAX_ERROR); - } - - // Testing whether the parsing works. - #[test] - fn prepare_statement_insert_parse() { - let mut out_statement = Statement::default(); - let cmd = String::from("insert 10 monkeylover ape@gmail.com"); - prepare_statement(&cmd, &mut out_statement); - assert_eq!(out_statement.row_instance, Row { - id: 10, - username: String::from("monkeylover"), - email: String::from("ape@gmail.com") - }); - } - - // Testing whether the parsing works by checking with incorrect data. - #[test] - fn prepare_statement_insert_parse_fail() { - let mut out_statement = Statement::default(); - let cmd = String::from("insert 10 monkeylover ape@gmail.com"); - prepare_statement(&cmd, &mut out_statement); - assert_ne!(out_statement.row_instance, Row { - id: 10, - username: String::from("blah"), - email: String::from("blah@gmail.com") - }); - } -} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index a224396..247dc24 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,15 @@ use crate::backend::*; -mod parser; +/* All our modules must be imported into either our main.rs or lib.rs to 'unite' them for the compiler. + * They cannot be imported into submodules, e.g backend.rs cannot do 'mod parser' as it would then expect + * to find a directory called /backend/parser.rs or /backend/parser/mod.rs. + */ mod backend; +mod parser; +mod tests { + mod unit_tests; +} fn main() { entrypoint(); -} \ No newline at end of file +} diff --git a/src/parser.rs b/src/parser.rs index 3131328..026f948 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -4,7 +4,7 @@ use scan_fmt::*; pub enum MetaCommandResult { SUCCESS, #[default] - UNRECOGNIZED + UNRECOGNIZED, } #[derive(PartialEq, Debug, Default)] @@ -12,34 +12,32 @@ pub enum PrepareResult { SUCCESS, #[default] UNRECOGNIZED, - SYNTAX_ERROR + SYNTAX_ERROR, } #[derive(PartialEq, Debug, Default)] pub enum StatementType { INSERT, #[default] - SELECT + SELECT, } #[derive(PartialEq, Debug, Default)] pub struct Statement { pub cmd: StatementType, - pub row_instance: Row + pub row_instance: Row, } #[derive(PartialEq, Debug, Default)] pub struct Row { pub id: u32, pub username: String, - pub email: String + pub email: String, } -pub fn prepare_statement(cmd: &String, statement: &mut Statement) -> PrepareResult -{ +pub fn prepare_statement(cmd: &String, statement: &mut Statement) -> PrepareResult { // First six chars are insert. We use a substring since this is followed by data. - if cmd.len() >= 6 && &cmd[0..6]== "insert" - { + if cmd.len() >= 6 && &cmd[0..6] == "insert" { statement.cmd = StatementType::INSERT; // This is how we take our formatted string and put it into variables. @@ -51,11 +49,14 @@ pub fn prepare_statement(cmd: &String, statement: &mut Statement) -> PrepareResu } }; - statement.row_instance = Row { id, username, email }; + statement.row_instance = Row { + id, + username, + email, + }; return PrepareResult::SUCCESS; } - if cmd == "select" - { + if cmd == "select" { statement.cmd = StatementType::SELECT; return PrepareResult::SUCCESS; } diff --git a/src/tests/integration.rs b/src/tests/integration.rs new file mode 100644 index 0000000..c184b28 --- /dev/null +++ b/src/tests/integration.rs @@ -0,0 +1,3 @@ +use crate::backend::*; +use crate::parser::*; + diff --git a/src/tests/unit_tests.rs b/src/tests/unit_tests.rs new file mode 100644 index 0000000..f909d07 --- /dev/null +++ b/src/tests/unit_tests.rs @@ -0,0 +1,87 @@ +use crate::backend::*; +use crate::parser::*; + +// Testing whether unrecognized commands are rejected. +#[test] +fn execute_command_unrecognized() { + let cmd = String::from(".dummy"); + let out = execute_command(&cmd); + assert_eq!(out, MetaCommandResult::UNRECOGNIZED); +} + +// Testing whether the enum is set properly. +#[test] +fn prepare_statement_set_insert() { + let mut out_statement = Statement::default(); + let cmd = String::from("insert"); + prepare_statement(&cmd, &mut out_statement); + assert_eq!(out_statement.cmd, StatementType::INSERT); +} + +// Testing whether the enum is set properly. +#[test] +fn prepare_statement_set_select() { + let mut out_statement = Statement::default(); + let cmd = String::from("select"); + prepare_statement(&cmd, &mut out_statement); + assert_eq!(out_statement.cmd, StatementType::SELECT); +} + +// Testing whether the output result is correct. +#[test] +fn prepare_statement_out_success() { + let mut out_statement = Statement::default(); + let cmd = String::from("insert 10 monkeylover ape@gmail.com"); + let out_result = prepare_statement(&cmd, &mut out_statement); + assert_eq!(out_result, PrepareResult::SUCCESS); +} + +// Testing whether the output result handles bad commands. +#[test] +fn prepare_statement_out_failure() { + let mut out_statement = Statement::default(); + let cmd = String::from("dummy"); + let out_result = prepare_statement(&cmd, &mut out_statement); + assert_eq!(out_result, PrepareResult::UNRECOGNIZED); +} + +// Testing whether the insert syntax error is handled. +#[test] +fn prepare_statement_out_syntax_error() { + let mut out_statement = Statement::default(); + let cmd = String::from("insert"); + let out_result = prepare_statement(&cmd, &mut out_statement); + assert_eq!(out_result, PrepareResult::SYNTAX_ERROR); +} + +// Testing whether the parsing works. +#[test] +fn prepare_statement_insert_parse() { + let mut out_statement = Statement::default(); + let cmd = String::from("insert 10 monkeylover ape@gmail.com"); + prepare_statement(&cmd, &mut out_statement); + assert_eq!( + out_statement.row_instance, + Row { + id: 10, + username: String::from("monkeylover"), + email: String::from("ape@gmail.com") + } + ); +} + +// Testing whether the parsing works by checking with incorrect data. +#[test] +fn prepare_statement_insert_parse_fail() { + let mut out_statement = Statement::default(); + let cmd = String::from("insert 10 monkeylover ape@gmail.com"); + prepare_statement(&cmd, &mut out_statement); + assert_ne!( + out_statement.row_instance, + Row { + id: 10, + username: String::from("blah"), + email: String::from("blah@gmail.com") + } + ); +}