diff --git a/src/backend.rs b/src/backend.rs index 425cec4..9d0d9e9 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -75,7 +75,7 @@ pub fn execute_command(cmd: &str) -> MetaCommandResult { } } -fn execute_statement(statement: Statement, tb: &mut Table) -> ExecuteResult { +pub fn execute_statement(statement: Statement, tb: &mut Table) -> ExecuteResult { match statement.cmd { StatementType::Insert => { println!("Performing an insert..."); diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..6265d54 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,2 @@ +pub mod backend; +pub mod parser; diff --git a/src/main.rs b/src/main.rs index 247dc24..f43a7ad 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,9 +6,6 @@ use crate::backend::*; */ mod backend; mod parser; -mod tests { - mod unit_tests; -} fn main() { entrypoint(); diff --git a/src/tests/unit_tests.rs b/src/tests/unit_tests.rs deleted file mode 100644 index ea33c32..0000000 --- a/src/tests/unit_tests.rs +++ /dev/null @@ -1,286 +0,0 @@ -#[cfg(test)] -use crate::{ - backend::execute_command, - parser::{prepare_statement, MetaCommandResult, PrepareResult, Row, Statement, StatementType}, -}; - -// Testing whether unrecognized commands are rejected. -#[test] -fn execute_command_unrecognized() { - let cmd = ".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 = "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 = "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 cmd = "insert 10 monkeylover ape@gmail.com"; - let out_result = prepare_statement(cmd, &mut Statement::default()); - assert_eq!(out_result, PrepareResult::Success); -} - -// Testing whether the output result handles bad commands. -#[test] -fn prepare_statement_out_failure() { - let cmd = "dummy"; - let out_result = prepare_statement(cmd, &mut Statement::default()); - 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 = "insert"; - let out_result = prepare_statement(cmd, &mut out_statement); - assert_eq!(out_result, PrepareResult::SyntaxError); -} - -// Testing whether the parsing works. -#[test] -fn prepare_statement_insert_parse() { - let mut out_statement = Statement::default(); - let cmd = "insert 10 monkeylover ape@gmail.com"; - prepare_statement(cmd, &mut out_statement); - assert_eq!( - out_statement.row_instance, - Some(Row { - id: 10, - username: "monkeylover".to_string(), - email: "ape@gmail.com".to_string() - }) - ); -} - -// 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 = "insert 10 monkeylover ape@gmail.com"; - prepare_statement(cmd, &mut out_statement); - assert_ne!( - out_statement.row_instance, - Some(Row { - id: 10, - username: "blah".to_string(), - email: "blah@gmail.com".to_string() - }) - ); -} - -// Testing insert with empty username -#[test] -fn prepare_statement_insert_empty_username() { - let mut out_statement = Statement::default(); - let cmd = "insert 10 ape@gmail.com"; - let out_result = prepare_statement(cmd, &mut out_statement); - assert_eq!(out_result, PrepareResult::SyntaxError); -} - -// Testing insert with empty email -#[test] -fn prepare_statement_insert_empty_email() { - let mut out_statement = Statement::default(); - let cmd = "insert 10 monkeylover "; - let out_result = prepare_statement(cmd, &mut out_statement); - assert_eq!(out_result, PrepareResult::SyntaxError); -} - -// Testing insert with invalid ID (not a number) -#[test] -fn prepare_statement_insert_invalid_id() { - let mut out_statement = Statement::default(); - let cmd = "insert abc monkeylover ape@gmail.com"; - let out_result = prepare_statement(cmd, &mut out_statement); - assert_eq!(out_result, PrepareResult::SyntaxError); -} - -// Testing insert with negative ID -#[test] -fn prepare_statement_insert_negative_id() { - let mut out_statement = Statement::default(); - let cmd = "insert -10 monkeylover ape@gmail.com"; - let out_result = prepare_statement(cmd, &mut out_statement); - assert_eq!(out_result, PrepareResult::SyntaxError); -} - -// Testing insert with very large ID -#[test] -fn prepare_statement_insert_large_id() { - let mut out_statement = Statement::default(); - let cmd = "insert 4294967295 monkeylover ape@gmail.com"; - let out_result = prepare_statement(cmd, &mut out_statement); - assert_eq!(out_result, PrepareResult::Success); -} - -// Testing insert with ID exceeding u32 max -#[test] -fn prepare_statement_insert_id_overflow() { - let mut out_statement = Statement::default(); - let cmd = "insert 4294967296 monkeylover ape@gmail.com"; - let out_result = prepare_statement(cmd, &mut out_statement); - assert_eq!(out_result, PrepareResult::SyntaxError); -} - -// Testing select with invalid ID -#[test] -fn prepare_statement_select_invalid_id() { - let mut out_statement = Statement::default(); - let cmd = "select abc"; - let out_result = prepare_statement(cmd, &mut out_statement); - assert_eq!(out_result, PrepareResult::SyntaxError); -} - -// Testing select with negative ID -#[test] -fn prepare_statement_select_negative_id() { - let mut out_statement = Statement::default(); - let cmd = "select -10"; - let out_result = prepare_statement(cmd, &mut out_statement); - assert_eq!(out_result, PrepareResult::SyntaxError); -} - -// Testing select with very large ID -#[test] -fn prepare_statement_select_large_id() { - let mut out_statement = Statement::default(); - let cmd = "select 4294967295"; - let out_result = prepare_statement(cmd, &mut out_statement); - assert_eq!(out_result, PrepareResult::Success); -} - -// Testing select with ID exceeding u32 max -#[test] -fn prepare_statement_select_id_overflow() { - let mut out_statement = Statement::default(); - let cmd = "select 4294967296"; - let out_result = prepare_statement(cmd, &mut out_statement); - assert_eq!(out_result, PrepareResult::SyntaxError); -} - -// Testing select with extra parameters -#[test] -fn prepare_statement_select_extra_params() { - let mut out_statement = Statement::default(); - let cmd = "select 10 extra"; - let out_result = prepare_statement(cmd, &mut out_statement); - assert_eq!(out_result, PrepareResult::Success); -} - -// Testing insert with extra parameters -#[test] -fn prepare_statement_insert_extra_params() { - let mut out_statement = Statement::default(); - let cmd = "insert 10 monkeylover ape@gmail.com extra"; - let out_result = prepare_statement(cmd, &mut out_statement); - assert_eq!(out_result, PrepareResult::Success); -} - -// Testing insert with special characters in username -#[test] -fn prepare_statement_insert_special_chars_username() { - let mut out_statement = Statement::default(); - let cmd = "insert 10 monkey_lover!@#$ ape@gmail.com"; - let out_result = prepare_statement(cmd, &mut out_statement); - assert_eq!(out_result, PrepareResult::Success); -} - -// Testing insert with special characters in email -#[test] -fn prepare_statement_insert_special_chars_email() { - let mut out_statement = Statement::default(); - let cmd = "insert 10 monkeylover ape+special@gmail.com"; - let out_result = prepare_statement(cmd, &mut out_statement); - assert_eq!(out_result, PrepareResult::Success); -} - -// Testing insert with very long username -#[test] -fn prepare_statement_insert_long_username() { - let mut out_statement = Statement::default(); - let cmd = format!("insert 10 {} ape@gmail.com", "a".repeat(1000)); - let out_result = prepare_statement(&cmd, &mut out_statement); - assert_eq!(out_result, PrepareResult::Success); -} - -// Testing insert with very long email -#[test] -fn prepare_statement_insert_long_email() { - let mut out_statement = Statement::default(); - let cmd = format!("insert 10 monkeylover {}@gmail.com", "a".repeat(1000)); - let out_result = prepare_statement(&cmd, &mut out_statement); - assert_eq!(out_result, PrepareResult::Success); -} - -// Testing case sensitivity in commands -#[test] -fn prepare_statement_case_sensitivity() { - let mut out_statement = Statement::default(); - let cmd = "INSERT 10 monkeylover ape@gmail.com"; - let out_result = prepare_statement(cmd, &mut out_statement); - assert_eq!(out_result, PrepareResult::Unrecognized); -} - -// Testing whitespace handling -#[test] -fn prepare_statement_whitespace_handling() { - let mut out_statement = Statement::default(); - let cmd = " insert 10 monkeylover ape@gmail.com "; - let out_result = prepare_statement(cmd, &mut out_statement); - assert_eq!(out_result, PrepareResult::Unrecognized); -} - -// Testing empty command -#[test] -fn prepare_statement_empty_command() { - let mut out_statement = Statement::default(); - let cmd = ""; - let out_result = prepare_statement(cmd, &mut out_statement); - assert_eq!(out_result, PrepareResult::Unrecognized); -} - -// Testing whitespace-only command -#[test] -fn prepare_statement_whitespace_only() { - let mut out_statement = Statement::default(); - let cmd = " "; - let out_result = prepare_statement(cmd, &mut out_statement); - assert_eq!(out_result, PrepareResult::Unrecognized); -} - -// Testing tab characters in command -#[test] -fn prepare_statement_tab_characters() { - let mut out_statement = Statement::default(); - let cmd = "insert\t10\tmonkeylover\tape@gmail.com"; - let out_result = prepare_statement(cmd, &mut out_statement); - assert_eq!(out_result, PrepareResult::Success); -} - -// Testing newline characters in command -#[test] -fn prepare_statement_newline_characters() { - let mut out_statement = Statement::default(); - let cmd = "insert\n10\nmonkeylover\nape@gmail.com"; - let out_result = prepare_statement(cmd, &mut out_statement); - assert_eq!(out_result, PrepareResult::Success); -} diff --git a/tests/backend_test.rs b/tests/backend_test.rs new file mode 100644 index 0000000..e919c2d --- /dev/null +++ b/tests/backend_test.rs @@ -0,0 +1,335 @@ +use sql_engine::backend::{execute_command, execute_statement, Table}; +use sql_engine::parser::{prepare_statement, MetaCommandResult, Row, Statement}; + +/// Helper method to quickly run SQL commands and mutate a table. +fn do_sql_cmd(tb: &mut Table, cmd: &str) { + let mut statement = Statement::default(); + prepare_statement(cmd, &mut statement); + execute_statement(statement, tb); +} + +#[test] +fn test_execute_statement_insert() { + let mut table = Table::new(); + do_sql_cmd(&mut table, "insert 13 rosh kakapio@gmail.com"); + + assert_eq!( + table.data, + vec![Row { + id: 13, + username: "rosh".to_string(), + email: "kakapio@gmail.com".to_string() + }] + ); +} + +#[test] +fn test_execute_statement_insert_fail() { + let mut table = Table::new(); + do_sql_cmd(&mut table, "insert 13 rosh kakapio@gmail.com"); + + assert_ne!( + table.data, + vec![Row { + id: 13, + username: "alfred".to_string(), + email: "alfredddd1@gmail.com".to_string() + }] + ); +} + +#[test] +fn test_execute_multiple_insert() { + let mut table = Table::new(); + do_sql_cmd(&mut table, "insert 13 rosh kakapio@gmail.com"); + do_sql_cmd(&mut table, "insert 42 stefan stefp@sigma.com"); + do_sql_cmd( + &mut table, + "insert 1699 sniper_penut penutterbutter@yahoo.com", + ); + + assert_eq!( + table.data, + vec![ + Row { + id: 13, + username: "rosh".to_string(), + email: "kakapio@gmail.com".to_string() + }, + Row { + id: 42, + username: "stefan".to_string(), + email: "stefp@sigma.com".to_string() + }, + Row { + id: 1699, + username: "sniper_penut".to_string(), + email: "penutterbutter@yahoo.com".to_string() + } + ] + ); +} + +#[test] +fn test_execute_select_empty_table() { + let mut table = Table::new(); + let mut statement = Statement::default(); + prepare_statement("select", &mut statement); + let result = execute_statement(statement, &mut table); + + if let sql_engine::backend::ExecuteResult::Success(Some(rows)) = result { + assert_eq!(rows.len(), 0); + } else { + panic!("Expected Success with empty vector"); + } +} + +#[test] +fn test_execute_select_nonexistent_id() { + let mut table = Table::new(); + do_sql_cmd(&mut table, "insert 13 rosh kakapio@gmail.com"); + + let mut statement = Statement::default(); + prepare_statement("select 42", &mut statement); + let result = execute_statement(statement, &mut table); + + if let sql_engine::backend::ExecuteResult::Success(Some(rows)) = result { + assert_eq!(rows.len(), 0); + } else { + panic!("Expected Success with empty vector"); + } +} + +#[test] +fn test_execute_select_existing_id() { + let mut table = Table::new(); + do_sql_cmd(&mut table, "insert 13 rosh kakapio@gmail.com"); + do_sql_cmd(&mut table, "insert 42 stefan stefp@sigma.com"); + + let mut statement = Statement::default(); + prepare_statement("select 42", &mut statement); + let result = execute_statement(statement, &mut table); + + if let sql_engine::backend::ExecuteResult::Success(Some(rows)) = result { + assert_eq!(rows.len(), 1); + assert_eq!(rows[0].id, 42); + assert_eq!(rows[0].username, "stefan"); + assert_eq!(rows[0].email, "stefp@sigma.com"); + } else { + panic!("Expected Success with one row"); + } +} + +#[test] +fn test_execute_select_all_multiple_rows() { + let mut table = Table::new(); + do_sql_cmd(&mut table, "insert 13 rosh kakapio@gmail.com"); + do_sql_cmd(&mut table, "insert 42 stefan stefp@sigma.com"); + do_sql_cmd( + &mut table, + "insert 1699 sniper_penut penutterbutter@yahoo.com", + ); + + let mut statement = Statement::default(); + prepare_statement("select", &mut statement); + let result = execute_statement(statement, &mut table); + + if let sql_engine::backend::ExecuteResult::Success(Some(rows)) = result { + assert_eq!(rows.len(), 3); + } else { + panic!("Expected Success with three rows"); + } +} + +#[test] +fn test_execute_insert_duplicate_id() { + let mut table = Table::new(); + do_sql_cmd(&mut table, "insert 13 rosh kakapio@gmail.com"); + do_sql_cmd(&mut table, "insert 13 stefan stefp@sigma.com"); + + assert_eq!( + table.data, + vec![ + Row { + id: 13, + username: "rosh".to_string(), + email: "kakapio@gmail.com".to_string() + }, + Row { + id: 13, + username: "stefan".to_string(), + email: "stefp@sigma.com".to_string() + } + ] + ); +} + +#[test] +fn test_execute_insert_zero_id() { + let mut table = Table::new(); + do_sql_cmd(&mut table, "insert 0 rosh kakapio@gmail.com"); + + assert_eq!( + table.data, + vec![Row { + id: 0, + username: "rosh".to_string(), + email: "kakapio@gmail.com".to_string() + }] + ); +} + +#[test] +fn test_execute_insert_max_id() { + let mut table = Table::new(); + do_sql_cmd(&mut table, "insert 4294967295 rosh kakapio@gmail.com"); + + assert_eq!( + table.data, + vec![Row { + id: 4294967295, + username: "rosh".to_string(), + email: "kakapio@gmail.com".to_string() + }] + ); +} + +#[test] +fn test_execute_select_zero_id() { + let mut table = Table::new(); + do_sql_cmd(&mut table, "insert 0 rosh kakapio@gmail.com"); + + let mut statement = Statement::default(); + prepare_statement("select 0", &mut statement); + let result = execute_statement(statement, &mut table); + + if let sql_engine::backend::ExecuteResult::Success(Some(rows)) = result { + assert_eq!(rows.len(), 1); + assert_eq!(rows[0].id, 0); + } else { + panic!("Expected Success with one row"); + } +} + +#[test] +fn test_execute_select_max_id() { + let mut table = Table::new(); + do_sql_cmd(&mut table, "insert 4294967295 rosh kakapio@gmail.com"); + + let mut statement = Statement::default(); + prepare_statement("select 4294967295", &mut statement); + let result = execute_statement(statement, &mut table); + + if let sql_engine::backend::ExecuteResult::Success(Some(rows)) = result { + assert_eq!(rows.len(), 1); + assert_eq!(rows[0].id, 4294967295); + } else { + panic!("Expected Success with one row"); + } +} + +#[test] +fn test_execute_insert_special_chars_username() { + let mut table = Table::new(); + do_sql_cmd(&mut table, "insert 13 rosh!@#$ kakapio@gmail.com"); + + assert_eq!( + table.data, + vec![Row { + id: 13, + username: "rosh!@#$".to_string(), + email: "kakapio@gmail.com".to_string() + }] + ); +} + +#[test] +fn test_execute_insert_special_chars_email() { + let mut table = Table::new(); + do_sql_cmd(&mut table, "insert 13 rosh kakapio+special@gmail.com"); + + assert_eq!( + table.data, + vec![Row { + id: 13, + username: "rosh".to_string(), + email: "kakapio+special@gmail.com".to_string() + }] + ); +} + +#[test] +fn test_execute_insert_long_username() { + let mut table = Table::new(); + let long_username = "a".repeat(1000); + do_sql_cmd( + &mut table, + &format!("insert 13 {} kakapio@gmail.com", long_username), + ); + + assert_eq!( + table.data, + vec![Row { + id: 13, + username: long_username, + email: "kakapio@gmail.com".to_string() + }] + ); +} + +#[test] +fn test_execute_insert_long_email() { + let mut table = Table::new(); + let long_email = format!("{}@gmail.com", "a".repeat(1000)); + do_sql_cmd(&mut table, &format!("insert 13 rosh {}", long_email)); + + assert_eq!( + table.data, + vec![Row { + id: 13, + username: "rosh".to_string(), + email: long_email, + }] + ); +} + +#[test] +fn test_execute_multiple_selects() { + let mut table = Table::new(); + do_sql_cmd(&mut table, "insert 13 rosh kakapio@gmail.com"); + do_sql_cmd(&mut table, "insert 42 stefan stefp@sigma.com"); + do_sql_cmd( + &mut table, + "insert 1699 sniper_penut penutterbutter@yahoo.com", + ); + + // Select all + let mut statement = Statement::default(); + prepare_statement("select", &mut statement); + let result = execute_statement(statement, &mut table); + + if let sql_engine::backend::ExecuteResult::Success(Some(rows)) = result { + assert_eq!(rows.len(), 3); + } else { + panic!("Expected Success with three rows"); + } + + // Select specific ID + let mut statement = Statement::default(); + prepare_statement("select 42", &mut statement); + let result = execute_statement(statement, &mut table); + + if let sql_engine::backend::ExecuteResult::Success(Some(rows)) = result { + assert_eq!(rows.len(), 1); + assert_eq!(rows[0].id, 42); + } else { + panic!("Expected Success with one row"); + } +} + +#[test] +fn test_execute_command_unrecognized() { + let cmd = ".dummy"; + let out = execute_command(cmd); + assert_eq!(out, MetaCommandResult::Unrecognized); +} diff --git a/tests/integration_test.rs b/tests/integration_test.rs new file mode 100644 index 0000000..46cd794 --- /dev/null +++ b/tests/integration_test.rs @@ -0,0 +1,254 @@ +use sql_engine::backend::{execute_command, execute_statement, Table}; +use sql_engine::parser::{prepare_statement, MetaCommandResult, Statement}; + +// Testing whether unrecognized commands are rejected. +#[test] +fn test_unrecognized_command() { + let cmd = ".dummy"; + let out = execute_command(cmd); + assert_eq!(out, MetaCommandResult::Unrecognized); +} + +// Testing a complete workflow of insert and select +#[test] +fn test_basic_workflow() { + let mut table = Table::new(); + + // Insert a row + let mut statement = Statement::default(); + prepare_statement("insert 42 testuser test@example.com", &mut statement); + let result = execute_statement(statement, &mut table); + + if let sql_engine::backend::ExecuteResult::Success(_) = result { + // Select the row + let mut statement = Statement::default(); + prepare_statement("select 42", &mut statement); + let result = execute_statement(statement, &mut table); + + if let sql_engine::backend::ExecuteResult::Success(Some(rows)) = result { + assert_eq!(rows.len(), 1); + assert_eq!(rows[0].id, 42); + assert_eq!(rows[0].username, "testuser"); + assert_eq!(rows[0].email, "test@example.com"); + } else { + panic!("Expected Success with one row"); + } + } else { + panic!("Expected Success for insert"); + } +} + +// Testing multiple operations in sequence +#[test] +fn test_multiple_operations() { + let mut table = Table::new(); + + // Insert multiple rows + let mut statement = Statement::default(); + prepare_statement("insert 1 user1 user1@example.com", &mut statement); + execute_statement(statement, &mut table); + + let mut statement = Statement::default(); + prepare_statement("insert 2 user2 user2@example.com", &mut statement); + execute_statement(statement, &mut table); + + let mut statement = Statement::default(); + prepare_statement("insert 3 user3 user3@example.com", &mut statement); + execute_statement(statement, &mut table); + + // Select all rows + let mut statement = Statement::default(); + prepare_statement("select", &mut statement); + let result = execute_statement(statement, &mut table); + + if let sql_engine::backend::ExecuteResult::Success(Some(rows)) = result { + assert_eq!(rows.len(), 3); + } else { + panic!("Expected Success with three rows"); + } + + // Select a specific row + let mut statement = Statement::default(); + prepare_statement("select 2", &mut statement); + let result = execute_statement(statement, &mut table); + + if let sql_engine::backend::ExecuteResult::Success(Some(rows)) = result { + assert_eq!(rows.len(), 1); + assert_eq!(rows[0].id, 2); + assert_eq!(rows[0].username, "user2"); + assert_eq!(rows[0].email, "user2@example.com"); + } else { + panic!("Expected Success with one row"); + } +} + +// Testing edge cases with special characters and whitespace +#[test] +fn test_special_characters() { + let mut table = Table::new(); + + // Insert with special characters in username and email + let mut statement = Statement::default(); + prepare_statement( + "insert 1 user@123 test.user+label@example.com", + &mut statement, + ); + let result = execute_statement(statement, &mut table); + assert!(matches!( + result, + sql_engine::backend::ExecuteResult::Success(_) + )); + + // Verify the data + let mut statement = Statement::default(); + prepare_statement("select 1", &mut statement); + let result = execute_statement(statement, &mut table); + + if let sql_engine::backend::ExecuteResult::Success(Some(rows)) = result { + assert_eq!(rows.len(), 1); + assert_eq!(rows[0].username, "user@123"); + assert_eq!(rows[0].email, "test.user+label@example.com"); + } else { + panic!("Expected Success with one row"); + } +} + +// Testing boundary values for IDs +#[test] +fn test_boundary_values() { + let mut table = Table::new(); + + // Test minimum value (0) + let mut statement = Statement::default(); + prepare_statement("insert 0 user0 zero@example.com", &mut statement); + let result = execute_statement(statement, &mut table); + assert!(matches!( + result, + sql_engine::backend::ExecuteResult::Success(_) + )); + + // Test maximum value (u32::MAX) + let mut statement = Statement::default(); + prepare_statement("insert 4294967295 usermax max@example.com", &mut statement); + let result = execute_statement(statement, &mut table); + assert!(matches!( + result, + sql_engine::backend::ExecuteResult::Success(_) + )); + + // Verify both entries + let mut statement = Statement::default(); + prepare_statement("select", &mut statement); + let result = execute_statement(statement, &mut table); + + if let sql_engine::backend::ExecuteResult::Success(Some(rows)) = result { + assert_eq!(rows.len(), 2); + assert_eq!(rows[0].id, 0); + assert_eq!(rows[1].id, 4294967295); + } else { + panic!("Expected Success with two rows"); + } +} + +// Testing duplicate IDs +#[test] +fn test_duplicate_ids() { + let mut table = Table::new(); + + // Insert first row + let mut statement = Statement::default(); + prepare_statement("insert 1 user1 user1@example.com", &mut statement); + execute_statement(statement, &mut table); + + // Insert duplicate ID + let mut statement = Statement::default(); + prepare_statement("insert 1 user2 user2@example.com", &mut statement); + execute_statement(statement, &mut table); + + // Verify both entries are present + let mut statement = Statement::default(); + prepare_statement("select", &mut statement); + let result = execute_statement(statement, &mut table); + + if let sql_engine::backend::ExecuteResult::Success(Some(rows)) = result { + assert_eq!(rows.len(), 2); + assert_eq!(rows[0].id, 1); + assert_eq!(rows[0].username, "user1"); + assert_eq!(rows[1].id, 1); + assert_eq!(rows[1].username, "user2"); + } else { + panic!("Expected Success with two rows"); + } +} + +// Testing select on empty table +#[test] +fn test_empty_table_operations() { + let mut table = Table::new(); + + // Select all from empty table + let mut statement = Statement::default(); + prepare_statement("select", &mut statement); + let result = execute_statement(statement, &mut table); + + if let sql_engine::backend::ExecuteResult::Success(Some(rows)) = result { + assert_eq!(rows.len(), 0); + } else { + panic!("Expected Success with zero rows"); + } + + // Select specific ID from empty table + let mut statement = Statement::default(); + prepare_statement("select 1", &mut statement); + let result = execute_statement(statement, &mut table); + + if let sql_engine::backend::ExecuteResult::Success(Some(rows)) = result { + assert_eq!(rows.len(), 0); + } else { + panic!("Expected Success with zero rows"); + } +} + +// Testing complex workflow with mixed operations +#[test] +fn test_complex_workflow() { + let mut table = Table::new(); + + // Insert multiple rows + let test_data = vec![ + ("insert 1 user1 user1@example.com", 1), + ("insert 2 user2 user2@example.com", 2), + ("insert 2 user2_dup user2_dup@example.com", 2), // Duplicate ID + ("insert 3 user3 user3@example.com", 3), + ]; + + for (cmd, _) in &test_data { + let mut statement = Statement::default(); + prepare_statement(cmd, &mut statement); + execute_statement(statement, &mut table); + } + + // Verify total count + let mut statement = Statement::default(); + prepare_statement("select", &mut statement); + let result = execute_statement(statement, &mut table); + + if let sql_engine::backend::ExecuteResult::Success(Some(rows)) = result { + assert_eq!(rows.len(), 4); + } + + // Verify each ID's count + for (_, id) in test_data { + let mut statement = Statement::default(); + prepare_statement(&format!("select {}", id), &mut statement); + let result = execute_statement(statement, &mut table); + + if let sql_engine::backend::ExecuteResult::Success(Some(rows)) = result { + if id == 2 { + assert_eq!(rows.len(), 2); // Should have two rows with ID 2 + } else { + assert_eq!(rows.len(), 1); + } + } + } +} diff --git a/tests/parser_test.rs b/tests/parser_test.rs new file mode 100644 index 0000000..112d8c6 --- /dev/null +++ b/tests/parser_test.rs @@ -0,0 +1,152 @@ +use sql_engine::parser::{ + prepare_statement, PrepareResult, Row, Statement, StatementType, +}; + +// Testing whether the enum is set properly. +#[test] +fn test_prepare_statement_set_insert() { + let mut out_statement = Statement::default(); + let cmd = "insert"; + prepare_statement(cmd, &mut out_statement); + assert_eq!(out_statement.cmd, StatementType::Insert); +} + +#[test] +fn test_prepare_statement_set_select() { + let mut out_statement = Statement::default(); + let cmd = "select"; + prepare_statement(cmd, &mut out_statement); + assert_eq!(out_statement.cmd, StatementType::Select); +} + +#[test] +fn test_prepare_statement_success() { + let cmd = "insert 10 monkeylover ape@gmail.com"; + let out_result = prepare_statement(cmd, &mut Statement::default()); + assert_eq!(out_result, PrepareResult::Success); +} + +#[test] +fn test_prepare_statement_unrecognized() { + let cmd = "dummy"; + let out_result = prepare_statement(cmd, &mut Statement::default()); + assert_eq!(out_result, PrepareResult::Unrecognized); +} + +#[test] +fn test_prepare_statement_syntax_error() { + let mut out_statement = Statement::default(); + let cmd = "insert"; + let out_result = prepare_statement(cmd, &mut out_statement); + assert_eq!(out_result, PrepareResult::SyntaxError); +} + +#[test] +fn test_prepare_statement_insert_parse() { + let mut out_statement = Statement::default(); + let cmd = "insert 10 monkeylover ape@gmail.com"; + prepare_statement(cmd, &mut out_statement); + assert_eq!( + out_statement.row_instance, + Some(Row { + id: 10, + username: "monkeylover".to_string(), + email: "ape@gmail.com".to_string() + }) + ); +} + +#[test] +fn test_prepare_statement_insert_parse_fail() { + let mut out_statement = Statement::default(); + let cmd = "insert 10 monkeylover ape@gmail.com"; + prepare_statement(cmd, &mut out_statement); + assert_ne!( + out_statement.row_instance, + Some(Row { + id: 10, + username: "blah".to_string(), + email: "blah@gmail.com".to_string() + }) + ); +} + +#[test] +fn test_prepare_statement_empty_username() { + let mut out_statement = Statement::default(); + let cmd = "insert 10 ape@gmail.com"; + let out_result = prepare_statement(cmd, &mut out_statement); + assert_eq!(out_result, PrepareResult::SyntaxError); +} + +#[test] +fn test_prepare_statement_empty_email() { + let mut out_statement = Statement::default(); + let cmd = "insert 10 monkeylover "; + let out_result = prepare_statement(cmd, &mut out_statement); + assert_eq!(out_result, PrepareResult::SyntaxError); +} + +#[test] +fn test_prepare_statement_invalid_id() { + let mut out_statement = Statement::default(); + let cmd = "insert abc monkeylover ape@gmail.com"; + let out_result = prepare_statement(cmd, &mut out_statement); + assert_eq!(out_result, PrepareResult::SyntaxError); +} + +#[test] +fn test_prepare_statement_negative_id() { + let mut out_statement = Statement::default(); + let cmd = "insert -10 monkeylover ape@gmail.com"; + let out_result = prepare_statement(cmd, &mut out_statement); + assert_eq!(out_result, PrepareResult::SyntaxError); +} + +#[test] +fn test_prepare_statement_large_id() { + let mut out_statement = Statement::default(); + let cmd = "insert 4294967295 monkeylover ape@gmail.com"; + let out_result = prepare_statement(cmd, &mut out_statement); + assert_eq!(out_result, PrepareResult::Success); +} + +#[test] +fn test_prepare_statement_id_overflow() { + let mut out_statement = Statement::default(); + let cmd = "insert 4294967296 monkeylover ape@gmail.com"; + let out_result = prepare_statement(cmd, &mut out_statement); + assert_eq!(out_result, PrepareResult::SyntaxError); +} + +#[test] +fn test_prepare_statement_case_sensitivity() { + let mut out_statement = Statement::default(); + let cmd = "INSERT 10 monkeylover ape@gmail.com"; + let out_result = prepare_statement(cmd, &mut out_statement); + assert_eq!(out_result, PrepareResult::Unrecognized); +} + +#[test] +fn test_prepare_statement_whitespace() { + let mut out_statement = Statement::default(); + let cmd = " insert 10 monkeylover ape@gmail.com "; + let out_result = prepare_statement(cmd, &mut out_statement); + assert_eq!(out_result, PrepareResult::Unrecognized); +} + +#[test] +fn test_prepare_statement_empty() { + let mut out_statement = Statement::default(); + let cmd = ""; + let out_result = prepare_statement(cmd, &mut out_statement); + assert_eq!(out_result, PrepareResult::Unrecognized); +} + +#[test] +fn test_prepare_statement_whitespace_only() { + let mut out_statement = Statement::default(); + let cmd = " "; + let out_result = prepare_statement(cmd, &mut out_statement); + assert_eq!(out_result, PrepareResult::Unrecognized); +}