From 83e45334a5b11329b062f4a0ec7c93e2e1e16f50 Mon Sep 17 00:00:00 2001 From: teo3300 Date: Sun, 26 Nov 2023 19:48:54 +0900 Subject: [PATCH] Adding tests - functional tests - more tests - tests tests tests Signed-off-by: teo3300 --- .git_hooks_pre-commit-shadow | 14 +++++++++- src/core.rs | 6 ++++- src/main.rs | 2 +- src/{tests => mal_tests}/mod.rs | 23 ++++++++++++---- src/types.rs | 47 +++++++++++++++++++++++++++++---- tests/assert_fail.mal | 1 + tests/logic.mal | 31 ++++++++++++++++++++++ 7 files changed, 111 insertions(+), 13 deletions(-) mode change 120000 => 100755 .git_hooks_pre-commit-shadow rename src/{tests => mal_tests}/mod.rs (67%) create mode 100644 tests/assert_fail.mal create mode 100644 tests/logic.mal diff --git a/.git_hooks_pre-commit-shadow b/.git_hooks_pre-commit-shadow deleted file mode 120000 index da0cb14..0000000 --- a/.git_hooks_pre-commit-shadow +++ /dev/null @@ -1 +0,0 @@ -.git/hooks/pre-commit \ No newline at end of file diff --git a/.git_hooks_pre-commit-shadow b/.git_hooks_pre-commit-shadow new file mode 100755 index 0000000..81a4942 --- /dev/null +++ b/.git_hooks_pre-commit-shadow @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +# Quit when first command fails +set -e + +# format code in a consistent way +cargo fmt + +# yeet on any clippy warning +cargo clippy -- -Dwarnings + +# check test pass +cargo test \ No newline at end of file diff --git a/src/core.rs b/src/core.rs index 0b7769c..4e1b281 100644 --- a/src/core.rs +++ b/src/core.rs @@ -50,7 +50,11 @@ pub fn ns_init() -> Env { "list?" => Fun(|a| Ok(Bool(a.iter().all(|el| matches!(el, List(_))))), "Return true if the first argument is a list, false otherwise"), "empty?" => Fun(|a| Ok(Bool(car(a)?.if_list()?.is_empty())), "Return true if the first parameter is an empty list, false otherwise, returns an error if the element is not a list"), "count" => Fun(|a| Ok(Int(car(a)?.if_list()?.len() as isize)), "Return the number of elements in the first argument"), + "and" => Fun(|a| Ok(Bool(a.iter().all(|a| !matches!(a, Nil | Bool(false))))), "Returns false if at least one of the arguments is 'false' or 'nil', true otherwise"), + "or" => Fun(|a| Ok(Bool(a.iter().any(|a| !matches!(a, Nil | Bool(false))))), "Returns false if all the arguments are 'false' or 'nil', true otherwise"), + "xor" => Fun(|a| Ok(Bool(a.iter().filter(|a| !matches!(a, Nil | Bool(false))).count() == 1)), "Returns true if one of the arguments is different from 'nil' or 'false', false otherwise"), + "not" => Fun(|a| Ok(Bool(matches!(car(a)?, Nil | Bool(false)))), "Negate the first argument"), "=" => Fun(mal_comp, "Return true if the first two parameters are the same type and content, in case of lists propagate to all elements"), - "assert" => Fun(mal_assert, "Panic if one of the arguments is false") + "assert" => Fun(mal_assert, "Return an error if assertion fails") ) } diff --git a/src/main.rs b/src/main.rs index fa8e3c2..1624bb5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,11 +4,11 @@ use std::env::args; mod core; mod env; mod eval; +mod mal_tests; mod parse_tools; mod printer; mod reader; mod step4_if_fn_do; -mod tests; mod types; use core::ns_init; diff --git a/src/tests/mod.rs b/src/mal_tests/mod.rs similarity index 67% rename from src/tests/mod.rs rename to src/mal_tests/mod.rs index 21ca527..a896dc6 100644 --- a/src/tests/mod.rs +++ b/src/mal_tests/mod.rs @@ -16,19 +16,32 @@ mod functional { ($file:expr) => {{ use crate::core::ns_init; use crate::load_file; - let env = ns_init(); - load_file!("core.mal", &env); - load_file!(format!("tests/{}.mal", $file).as_str(), &env); + load_file!(format!("tests/{}.mal", $file).as_str(), &ns_init()); }}; } #[test] - fn fibonacci() { - test!("fibonacci"); + fn assert_fail() { + use crate::core::ns_init; + use crate::load_file; + assert!(matches!( + load_file("tests/assert_fail.mal", &ns_init()), + Err(_) + )) + } + + #[test] + fn builtin_logic() { + test!("logic") } #[test] fn builtin_equals() { test!("equals"); } + + #[test] + fn fibonacci() { + test!("fibonacci"); + } } diff --git a/src/types.rs b/src/types.rs index e320c1e..0982b89 100644 --- a/src/types.rs +++ b/src/types.rs @@ -94,11 +94,11 @@ pub fn mal_comp(args: &[MalType]) -> MalRet { } pub fn mal_assert(args: &[MalType]) -> MalRet { - args.iter().for_each(|i| match i { - M::Nil | M::Bool(false) => panic!(), - _ => (), - }); - Ok(M::Nil) + if args.iter().any(|i| matches!(i, M::Nil | M::Bool(false))) { + Err(MalErr::unrecoverable("Assertion failed")) + } else { + Ok(M::Nil) + } } #[derive(PartialEq, Clone, Copy)] @@ -184,3 +184,40 @@ pub fn unescape_str(s: &str) -> String { .replace("\\n", "\n") .replace("\\\"", "\"") } + +//////////////////////////////////////////////////////////////////////////////// +// Tests // +//////////////////////////////////////////////////////////////////////////////// + +#[cfg(test)] +mod tests { + use crate::types::mal_assert; + use crate::types::MalType as M; + + #[test] + fn _mal_assert() { + assert!(matches!(mal_assert(&[M::Nil]), Err(_))); + assert!(matches!(mal_assert(&[M::Bool(false)]), Err(_))); + assert!(matches!(mal_assert(&[M::Bool(true)]), Ok(_))); + assert!(matches!(mal_assert(&[M::Int(1)]), Ok(_))); + } + + #[test] + fn _escape_str() { + use crate::types::escape_str; + assert_eq!(escape_str(""), "\"\""); // add quotations + assert_eq!(escape_str("\\"), "\"\\\\\""); // escape "\" + assert_eq!(escape_str("\n"), "\"\\n\""); // escape "\n" + assert_eq!(escape_str("\""), "\"\\\"\""); // escape "\"" + } + + #[test] + fn _unescape_str() { + use crate::types::unescape_str; + assert_eq!(unescape_str("\"\""), ""); // remove quotations + assert_eq!(unescape_str("\"a\""), "a"); // remove quotations + assert_eq!(unescape_str("\"\\\\\""), "\\"); // unescape "\" + assert_eq!(unescape_str("\"\\n\""), "\n"); // unescape "\n" + assert_eq!(unescape_str("\"\\\"\""), "\""); // unescape "\"" + } +} diff --git a/tests/assert_fail.mal b/tests/assert_fail.mal new file mode 100644 index 0000000..ec3f2d1 --- /dev/null +++ b/tests/assert_fail.mal @@ -0,0 +1 @@ +(assert nil) \ No newline at end of file diff --git a/tests/logic.mal b/tests/logic.mal new file mode 100644 index 0000000..71429be --- /dev/null +++ b/tests/logic.mal @@ -0,0 +1,31 @@ +; positive assert +(assert true) +(assert ()) +(assert 1) + +; not +(assert (not false)) +(assert (not nil)) +(assert (not (not true))) + +; or +(assert (not (or false))) +(assert (or 1)) +(assert (or 1 nil false)) +(assert (or 1 1 1)) +(assert (or nil 1 false)) +(assert (not (or nil false))) +(assert (not (or false nil))) + +; and +(assert (and 1)) +(assert (not (and nil))) +(assert (and 1 1 1)) +(assert (not (and 1 nil false))) +(assert (not (and nil false))) + +; xor +(assert (not (xor nil false nil))) +(assert (xor nil 1 nil false nil)) +(assert (not (xor nil 1 false 1))) +(assert (not (xor 1 nil 1 1))) \ No newline at end of file