Adding tests

- functional tests
- more tests
- tests tests tests

Signed-off-by: teo3300 <matteo.rogora@live.it>
This commit is contained in:
teo3300
2023-11-26 19:48:54 +09:00
parent 1f47c9f57e
commit 83e45334a5
7 changed files with 111 additions and 13 deletions

View File

@ -1 +0,0 @@
.git/hooks/pre-commit

13
.git_hooks_pre-commit-shadow Executable file
View File

@ -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

View File

@ -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")
)
}

View File

@ -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;

View File

@ -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");
}
}

View File

@ -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 "\""
}
}

1
tests/assert_fail.mal Normal file
View File

@ -0,0 +1 @@
(assert nil)

31
tests/logic.mal Normal file
View File

@ -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)))