Files
uclisp/test/test_e2e.c

288 lines
7.3 KiB
C

#include <stdlib.h>
#include <unity.h>
#include <string.h>
#include "uclisp.h"
#include "internal.h"
#include "utility.h"
#include "testing_helpers.h"
#include "state.h"
#include "builtins.h"
#include "special.h"
static struct ucl_object *input;
static struct ucl_object *response;
static struct ucl_state *state;
void setUp(void) {
input = NULL;
response = NULL;
state = ucl_state_create();
ucl_state_put(state, "let", ucl_special_create(ucl_special_let));
ucl_state_put(state, "defun", ucl_special_create(ucl_special_defun));
ucl_state_put(state, "+", ucl_builtin_create(ucl_builtin_add));
ucl_state_put(state, "error", ucl_builtin_create(ucl_builtin_error));
ucl_state_put(state, "list", ucl_builtin_create(ucl_builtin_list));
ucl_state_put(state, "setq", ucl_special_create(ucl_special_setq));
ucl_state_put(state, "car", ucl_builtin_create(ucl_builtin_car));
ucl_state_put(state, "cdr", ucl_builtin_create(ucl_builtin_cdr));
ucl_state_put(state, "nth", ucl_builtin_create(ucl_builtin_nth));
ucl_state_put(state, "mapcar", ucl_builtin_create(ucl_builtin_mapcar));
ucl_state_put(state, "lambda", ucl_special_create(ucl_special_lambda));
ucl_state_put(state, "quote", ucl_special_create(ucl_special_quote));
}
void tearDown(void) {
// TODO: Implement GC so we can clean these both up
//ucl_object_delete(input);
input = NULL;
ucl_state_delete(state);
ucl_gc();
response = NULL;
state = NULL;
}
static struct ucl_object *eval (const char *code) {
struct ucl_object *sexp = ucl_parse(code);
return ucl_evaluate(state, ucl_car(sexp));
}
void test_simple_add(void) {
ucl_state_put(state, "+", ucl_builtin_create(ucl_builtin_add));
response = eval("(+ 2 3)");
TEST_ASSERT_OBJ_INT(response);
TEST_ASSERT_EQUAL(response->integer, 5);
}
void test_simple_let(void) {
response = eval("(let ((x 2)) (+ x 3))");
TEST_ASSERT_OBJ_INT(response);
TEST_ASSERT_EQUAL(response->integer, 5);
}
void test_let_assignment_error(void) {
response = eval("(let ((x (error \"foo\"))) (+ x 3))");
TEST_ASSERT_OBJ_ERROR(response);
}
void test_nested_let(void) {
response = eval("(let ((x 2)) (let ((y 5)) (+ x y)))");
TEST_ASSERT_OBJ_INT(response);
TEST_ASSERT_EQUAL(response->integer, 7);
}
void test_nested_let_scope(void) {
response = eval("(let ((x 2)) (let ((y 5)) (+ x y)) y)");
TEST_ASSERT_OBJ_ERROR(response);
}
void test_multi_let(void) {
response = eval("(let ((x 2)(y 5)) (+ x y))");
TEST_ASSERT_OBJ_INT(response);
TEST_ASSERT_EQUAL(response->integer, 7);
}
void test_let_return_sym(void) {
response = eval("(let ((x 2)) x)");
TEST_ASSERT_OBJ_INT(response);
TEST_ASSERT_EQUAL(response->integer, 2);
}
void test_eval_int(void) {
response = eval("2");
TEST_ASSERT_OBJ_INT(response);
TEST_ASSERT_EQUAL(response->integer, 2);
}
void test_eval_string(void) {
response = eval("\"foo\"");
TEST_ASSERT_OBJ_STRING(response);
TEST_ASSERT_EQUAL_STRING(response->string, "foo");
}
void test_eval_sym_defined(void) {
ucl_state_put(state, "foo", ucl_int_create(2));
response = eval("foo");
TEST_ASSERT_OBJ_INT(response);
TEST_ASSERT_EQUAL(response->integer, 2);
}
void test_eval_sym_undefined(void) {
response = eval("foo");
TEST_ASSERT_OBJ_ERROR(response);
}
void test_eval_nested_error(void) {
response = eval("(+ (error \"foo\") 3)");
TEST_ASSERT_OBJ_ERROR(response);
}
void test_eval_list(void) {
response = eval("(list 1 2 3)");
TEST_ASSERT_OBJ_LIST(response);
TEST_ASSERT_EQUAL(ucl_list_length(response)->integer, 3);
int i = 1;
FOREACH_LIST(response, iter, item) {
TEST_ASSERT_EQUAL(item->integer, i);
i++;
}
}
void test_eval_defun(void) {
response = eval("(defun foo (a b) (+ a b))");
TEST_ASSERT_OBJ_SYMBOL(response);
TEST_ASSERT_EQUAL_STRING(response->symbol, "foo");
}
void test_call_function(void) {
response = eval("(defun foo (a b) (+ a b))");
TEST_ASSERT_OBJ_SYMBOL(response);
TEST_ASSERT_EQUAL_STRING(response->symbol, "foo");
response = eval("(foo 2 3)");
TEST_ASSERT_OBJ_INT(response);
TEST_ASSERT_EQUAL(response->integer, 5);
}
void test_setq(void) {
response = eval("(setq bar 123)");
TEST_ASSERT_OBJ_INT(response);
TEST_ASSERT_EQUAL(response->symbol, 123);
response = eval("bar");
TEST_ASSERT_OBJ_INT(response);
TEST_ASSERT_EQUAL(response->symbol, 123);
}
void test_setq_from_function(void) {
response = eval("(defun foo (a) (setq bar a))");
TEST_ASSERT_OBJ_SYMBOL(response);
TEST_ASSERT_EQUAL_STRING(response->symbol, "foo");
response = eval("(foo 2)");
TEST_ASSERT_OBJ_INT(response);
TEST_ASSERT_EQUAL(response->symbol, 2);
response = eval("bar");
TEST_ASSERT_OBJ_INT(response);
TEST_ASSERT_EQUAL(response->symbol, 2);
}
void test_lambda(void) {
response = eval("((lambda (x) (+ x 2)) 2)");
TEST_ASSERT_OBJ_INT(response);
TEST_ASSERT_EQUAL(response->integer, 4);
}
void test_mapcar_lambda(void) {
response = eval("(car (mapcar (quote (lambda (x) (+ x 2))) (list 5)))");
TEST_ASSERT_OBJ_INT(response);
TEST_ASSERT_EQUAL(response->integer, 7);
}
void test_mapcar_function(void) {
response = eval("(defun foo (a) (+ a 2))");
TEST_ASSERT_OBJ_SYMBOL(response);
TEST_ASSERT_EQUAL_STRING(response->symbol, "foo");
response = eval("(car (mapcar (quote foo) (list 5)))");
TEST_ASSERT_OBJ_INT(response);
TEST_ASSERT_EQUAL(response->integer, 7);
}
void test_car(void) {
response = eval("(car (list 2 3 4))");
TEST_ASSERT_OBJ_INT(response);
TEST_ASSERT_EQUAL(response->integer, 2);
}
void test_cdr(void) {
response = eval("(car (cdr (list 2 3 4)))");
TEST_ASSERT_OBJ_INT(response);
TEST_ASSERT_EQUAL(response->integer, 3);
}
void test_nth_0(void) {
response = eval("(nth 0 (list 2 3 4))");
TEST_ASSERT_OBJ_INT(response);
TEST_ASSERT_EQUAL(response->integer, 2);
}
void test_nth_1(void) {
response = eval("(nth 1 (list 2 3 4))");
TEST_ASSERT_OBJ_INT(response);
TEST_ASSERT_EQUAL(response->integer, 3);
}
void test_nth_oob(void) {
response = eval("(nth 3 (list 2 3 4))");
TEST_ASSERT_OBJ_ERROR(response);
}
void test_eval_defun_gc(void) {
response = eval("(defun foo (a b) (+ a b))");
TEST_ASSERT_OBJ_SYMBOL(response);
TEST_ASSERT_EQUAL_STRING(response->symbol, "foo");
ucl_gc();
response = eval("(foo 10 15)");
TEST_ASSERT_OBJ_INT(response);
TEST_ASSERT_EQUAL(response->integer, 25);
}
int main(void) {
UNITY_BEGIN();
RUN_TEST(test_simple_add);
RUN_TEST(test_simple_let);
RUN_TEST(test_let_assignment_error);
RUN_TEST(test_nested_let);
RUN_TEST(test_nested_let_scope);
RUN_TEST(test_multi_let);
RUN_TEST(test_let_return_sym);
RUN_TEST(test_eval_int);
RUN_TEST(test_eval_string);
RUN_TEST(test_eval_sym_defined);
RUN_TEST(test_eval_sym_undefined);
RUN_TEST(test_eval_nested_error);
RUN_TEST(test_eval_list);
RUN_TEST(test_eval_defun);
RUN_TEST(test_call_function);
RUN_TEST(test_setq);
RUN_TEST(test_setq_from_function);
RUN_TEST(test_lambda);
RUN_TEST(test_mapcar_lambda);
RUN_TEST(test_car);
RUN_TEST(test_cdr);
RUN_TEST(test_nth_0);
RUN_TEST(test_nth_1);
RUN_TEST(test_nth_oob);
RUN_TEST(test_eval_defun_gc);
return UNITY_END();
}