|
- #define epsilon 2.2204460492503131E-16
-
- #define testresult int
- #define pass 1
- #define fail 0
-
- #define print_assert_equal_fail(variable, value, type, format) \
- printf("\n%s:%d: Assertion failed\n\tfor '" #variable "'" \
- "\n\texpected: " format \
- "\n\tgot: " format "\n", \
- __FILE__, __LINE__, (type)value, (type)variable)
-
- #define print_assert_not_equal_fail(variable, value, type, format) \
- printf("\n%s:%d: Assertion failed\n\tfor '" #variable "'" \
- "\n\texpected not: " format \
- "\n\tgot anyways: " format "\n", \
- __FILE__, __LINE__, (type)value, (type)variable)
-
- #define assert_no_error(error) \
- if (error) { \
- printf("\nExpected no error to occur," \
- " but an error occured anyways:\n"); \
- log_error(); \
- return fail; \
- } \
-
- #define assert_equal_int(variable, value) \
- if (variable != value) { \
- print_assert_equal_fail(variable, value, size_t, "%zd"); \
- return fail; \
- }
-
- #define assert_not_equal_int(variable, value) \
- if (variable == value) { \
- print_assert_not_equal_fail(variable, value, size_t, "%zd"); \
- return fail; \
- }
-
- #define assert_equal_double(variable, value) \
- if (fabs((double)variable - (double)value) > epsilon) { \
- print_assert_equal_fail(variable, value, double, "%f"); \
- return fail; \
- }
-
- #define assert_not_equal_double(variable, value) \
- if (fabs((double)variable - (double)value) <= epsilon) { \
- print_assert_not_equal_fail(variable, value, double, "%f"); \
- return fail; \
- }
-
- #define assert_equal_string(variable, value) \
- if (!string_equal(variable, value)) { \
- print_assert_equal_fail(variable, value, char*, "%s"); \
- return fail; \
- }
-
- #define assert_equal_type(node, _type) \
- if (node->type != _type) { \
- print_assert_equal_fail( \
- Ast_Node_Type_to_string(node->type), \
- Ast_Node_Type_to_string(_type), char*, "%s"); \
- return fail; \
- } \
-
- #define assert_null(variable) \
- assert_equal_int(variable, nullptr)
-
- #define assert_not_null(variable) \
- assert_not_equal_int(variable, nullptr)
-
- #define invoke_test(name) \
- printf("" #name ":"); \
- if (name() == pass) { \
- for(size_t i = strlen(#name); i < 70; ++i) \
- printf((i%3==1)? "." : " "); \
- printf("%spassed%s\n", console_green, console_normal); \
- } \
- else { \
- for(int i = -1; i < 70; ++i) \
- printf((i%3==1)? "." : " "); \
- printf("%sfailed%s\n", console_red, console_normal); \
- if(error) { \
- free(error); \
- error = nullptr; \
- } \
- } \
-
- testresult test_eval_operands() {
- char operands_string[] = "((eval 1) (+ 1 2) \"okay\" (eval :haha))";
- Ast_Node* operands = parse_single_expression(operands_string);
- int operands_length;
- operands = eval_arguments(operands, create_empty_environment(Environment_Type_Let), &operands_length);
-
- assert_no_error(error);
- assert_equal_int(list_length(operands), 4);
-
- assert_equal_type(operands, Ast_Node_Type_Pair);
- assert_equal_type(operands->value.pair->first, Ast_Node_Type_Number);
- assert_equal_double(operands->value.pair->first->value.number->value, 1);
-
- operands = operands->value.pair->rest;
-
- assert_equal_type(operands, Ast_Node_Type_Pair);
- assert_equal_type(operands->value.pair->first, Ast_Node_Type_Number);
- assert_equal_double(operands->value.pair->first->value.number->value, 3);
-
- operands = operands->value.pair->rest;
-
- assert_equal_type(operands, Ast_Node_Type_Pair);
- assert_equal_type(operands->value.pair->first, Ast_Node_Type_String);
- assert_equal_string(operands->value.pair->first->value.string->value, "okay");
-
- operands = operands->value.pair->rest;
-
- assert_equal_type(operands, Ast_Node_Type_Pair);
- assert_equal_type(operands->value.pair->first, Ast_Node_Type_Keyword);
- assert_equal_string(operands->value.pair->first->value.keyword->identifier, "haha");
-
- return pass;
- }
-
- testresult test_parse_atom() {
- int index_in_text = 0;
- char string[] =
- "123 -1.23e-2 " // numbers
- "\"asd\" " // strings
- ":key1 :key:2 " // keywords
- "sym +"; // symbols
-
- // test numbers
- Ast_Node* result = parse_atom(string, &index_in_text);
-
- assert_equal_type(result, Ast_Node_Type_Number);
- assert_equal_double(result->value.number->value, 123);
-
- ++index_in_text;
-
- result = parse_atom(string, &index_in_text);
- assert_equal_type(result, Ast_Node_Type_Number);
- assert_equal_double(result->value.number->value, -1.23e-2);
-
- // test strings
- ++index_in_text;
-
- result = parse_atom(string, &index_in_text);
- assert_equal_type(result, Ast_Node_Type_String);
- assert_equal_string(result->value.string->value, "asd");
-
- // test keywords
- ++index_in_text;
-
- result = parse_atom(string, &index_in_text);
- assert_equal_type(result, Ast_Node_Type_Keyword);
- assert_equal_string(result->value.keyword->identifier, "key1");
-
- ++index_in_text;
-
- result = parse_atom(string, &index_in_text);
- assert_equal_type(result, Ast_Node_Type_Keyword);
- assert_equal_string(result->value.keyword->identifier, "key:2");
-
- // test symbols
- ++index_in_text;
-
- result = parse_atom(string, &index_in_text);
- assert_equal_type(result, Ast_Node_Type_Symbol);
- assert_equal_string(result->value.symbol->identifier, "sym");
-
- ++index_in_text;
-
- result = parse_atom(string, &index_in_text);
- assert_equal_type(result, Ast_Node_Type_Symbol);
- assert_equal_string(result->value.symbol->identifier, "+");
-
- return pass;
- }
-
- testresult test_parse_expression() {
- int index_in_text = 0;
- char string[] = "(fun + 12)";
-
- Ast_Node* result = parse_expression(string, &index_in_text);
- assert_no_error(error);
-
- assert_equal_type(result, Ast_Node_Type_Pair);
- assert_equal_type(result->value.pair->first, Ast_Node_Type_Symbol);
- assert_equal_string(result->value.pair->first->value.symbol->identifier, "fun");
-
- result = result->value.pair->rest;
-
- assert_equal_type(result, Ast_Node_Type_Pair);
- assert_equal_type(result->value.pair->first, Ast_Node_Type_Symbol);
- assert_equal_string(result->value.pair->first->value.symbol->identifier, "+");
-
- result = result->value.pair->rest;
-
- assert_equal_type(result, Ast_Node_Type_Pair);
- assert_equal_type(result->value.pair->first, Ast_Node_Type_Number);
- assert_equal_double(result->value.pair->first->value.number->value, 12);
-
- result = result->value.pair->rest;
-
- assert_equal_type(result, Ast_Node_Type_Nil);
-
- char string2[] = "(define fun (lambda (x) (+ 5 (* x x ))))";
- index_in_text = 0;
-
- result = parse_expression(string2, &index_in_text);
- assert_no_error(error);
-
- assert_equal_type(result, Ast_Node_Type_Pair);
- assert_equal_type(result->value.pair->first, Ast_Node_Type_Symbol);
- assert_equal_string(result->value.pair->first->value.symbol->identifier, "define");
-
- result = result->value.pair->rest;
-
- assert_equal_type(result, Ast_Node_Type_Pair);
- assert_equal_type(result->value.pair->first, Ast_Node_Type_Symbol);
- assert_equal_string(result->value.pair->first->value.symbol->identifier, "fun");
-
- result = result->value.pair->rest;
-
- assert_equal_type(result, Ast_Node_Type_Pair);
- assert_equal_type(result->value.pair->first, Ast_Node_Type_Pair);
- assert_equal_type(result->value.pair->first->value.pair->first, Ast_Node_Type_Symbol);
- assert_equal_string(result->value.pair->first->value.pair->first->value.symbol->identifier, "lambda");
-
- result = result->value.pair->rest;
-
- return pass;
- }
-
- testresult test_built_in_add() {
- char exp_string[] = "(+ 10 4)";
- Ast_Node* expression = parse_single_expression(exp_string);
- Ast_Node* result = eval_expr(expression, create_empty_environment(Environment_Type_Let));
-
- assert_no_error(error);
- assert_not_null(result);
- assert_equal_type(result, Ast_Node_Type_Number);
- assert_equal_double(result->value.number->value, 14);
-
- return pass;
- }
-
- testresult test_built_in_substract() {
- char exp_string[] = "(- 10 4)";
- Ast_Node* expression = parse_single_expression(exp_string);
- Ast_Node* result = eval_expr(expression, create_empty_environment(Environment_Type_Let));
-
- assert_no_error(error);
- assert_not_null(result);
- assert_equal_type(result, Ast_Node_Type_Number);
- assert_equal_double(result->value.number->value, 6);
-
- return pass;
- }
-
-
- testresult test_built_in_multiply() {
- char exp_string[] = "(* 10 4)";
- Ast_Node* expression = parse_single_expression(exp_string);
- Ast_Node* result = eval_expr(expression, create_empty_environment(Environment_Type_Let));
-
- assert_no_error(error);
- assert_not_null(result);
- assert_equal_type(result, Ast_Node_Type_Number);
- assert_equal_double(result->value.number->value, 40);
-
- return pass;
- }
-
-
- testresult test_built_in_divide() {
- char exp_string[] = "(/ 20 4)";
- Ast_Node* expression = parse_single_expression(exp_string);
- Ast_Node* result = eval_expr(expression, create_empty_environment(Environment_Type_Let));
-
- assert_null(error);
- assert_not_null(result);
- assert_equal_type(result, Ast_Node_Type_Number);
- assert_equal_double(result->value.number->value, 5);
-
- return pass;
- }
-
-
- testresult test_built_in_if() {
- char exp_string1[] = "(if 1 4 5)";
- Ast_Node* expression = parse_single_expression(exp_string1);
- Ast_Node* result = eval_expr(expression, create_empty_environment(Environment_Type_Let));
-
- assert_no_error(error);
- assert_not_null(result);
- assert_equal_type(result, Ast_Node_Type_Number);
- assert_equal_double(result->value.number->value, 4);
-
- char exp_string2[] = "(if () 4 5)";
- expression = parse_single_expression(exp_string2);
- result = eval_expr(expression, create_empty_environment(Environment_Type_Let));
-
- assert_no_error(error);
- assert_not_null(result);
- assert_equal_type(result, Ast_Node_Type_Number);
- assert_equal_double(result->value.number->value, 5);
-
- return pass;
- }
-
- testresult test_built_in_and() {
- char exp_string1[] = "(and 1 \"asd\" 4)";
- Ast_Node* expression = parse_single_expression(exp_string1);
- Ast_Node* result = eval_expr(expression, create_empty_environment(Environment_Type_Let));
-
- assert_no_error(error);
- assert_not_null(result);
- assert_equal_type(result, Ast_Node_Type_Number);
- assert_equal_double(result->value.number->value, 1);
-
- // a false case
- char exp_string2[] = "(and () \"asd\" 4)";
- expression = parse_single_expression(exp_string2);
- result = eval_expr(expression, create_empty_environment(Environment_Type_Let));
-
- assert_no_error(error);
- assert_not_null(result);
- assert_equal_type(result, Ast_Node_Type_Nil);
-
- return pass;
- }
-
- testresult test_built_in_or() {
- char exp_string1[] = "(or \"asd\" nil)";
- Ast_Node* expression = parse_single_expression(exp_string1);
- Ast_Node* result = eval_expr(expression, create_empty_environment(Environment_Type_Let));
-
- assert_no_error(error);
- assert_not_null(result);
- assert_equal_type(result, Ast_Node_Type_Number);
- assert_equal_double(result->value.number->value, 1);
-
- // a false case
- char exp_string2[] = "(or () ())";
- expression = parse_single_expression(exp_string2);
- result = eval_expr(expression, create_empty_environment(Environment_Type_Let));
-
- assert_no_error(error);
- assert_not_null(result);
- assert_equal_type(result, Ast_Node_Type_Nil);
-
- return pass;
- }
-
-
- testresult test_built_in_not() {
- char exp_string1[] = "(not ())";
- Ast_Node* expression = parse_single_expression(exp_string1);
- Ast_Node* result = eval_expr(expression, create_empty_environment(Environment_Type_Let));
-
- // a true case
- assert_no_error(error);
- assert_not_null(result);
- assert_equal_type(result, Ast_Node_Type_Number);
- assert_equal_double(result->value.number->value, 1);
-
- // a false case
- char exp_string2[] = "(not \"asd xD\")";
- expression = parse_single_expression(exp_string2);
- result = eval_expr(expression, create_empty_environment(Environment_Type_Let));
-
- assert_no_error(error);
- assert_not_null(result);
- assert_equal_type(result, Ast_Node_Type_Nil);
-
- return pass;
- }
-
- void run_all_tests() {
- log_level = Log_Level_None;
-
- printf("-- Parsing --\n");
- invoke_test(test_parse_atom);
- invoke_test(test_parse_expression);
-
- printf("\n-- Basic evaluating --\n");
- invoke_test(test_eval_operands);
-
- printf("\n-- Built ins --\n");
- invoke_test(test_built_in_add);
- invoke_test(test_built_in_substract);
- invoke_test(test_built_in_multiply);
- invoke_test(test_built_in_divide);
- invoke_test(test_built_in_if);
- invoke_test(test_built_in_and);
- invoke_test(test_built_in_or);
- invoke_test(test_built_in_not);
-
- }
|