diff --git a/Makefile b/Makefile index d5169d9..81b490d 100644 --- a/Makefile +++ b/Makefile @@ -260,17 +260,17 @@ benchmark: test_benchmark @python3 examples/benchmark.py @echo "" -test_nanbox: tests/test_nanbox.c runtime/nanbox.h - $(CC) $(CFLAGS) -o $@ tests/test_nanbox.c $(LDFLAGS) +test_nanbox: tests/test_nanbox.c runtime/nanbox.h $(UNITTEST_OBJECTS) + $(CC) $(CFLAGS) -o $@ tests/test_nanbox.c $(UNITTEST_OBJECTS) $(LDFLAGS) -test_fastframe: tests/test_fastframe.c runtime/fastframe.c runtime/nanbox.h runtime/fastframe.h - $(CC) $(CFLAGS) -o $@ tests/test_fastframe.c runtime/fastframe.c $(LDFLAGS) +test_fastframe: tests/test_fastframe.c runtime/fastframe.c runtime/nanbox.h runtime/fastframe.h $(UNITTEST_OBJECTS) + $(CC) $(CFLAGS) -o $@ tests/test_fastframe.c runtime/fastframe.c $(UNITTEST_OBJECTS) $(LDFLAGS) -test_labeltable: tests/test_labeltable.c runtime/labeltable.c $(IR_OBJECTS) $(TYPES_OBJECTS) $(SEMANTIC_OBJECTS) - $(CC) $(CFLAGS) -o $@ tests/test_labeltable.c runtime/labeltable.c $(IR_OBJECTS) $(TYPES_OBJECTS) $(SEMANTIC_OBJECTS) $(LDFLAGS) +test_labeltable: tests/test_labeltable.c runtime/labeltable.c $(IR_OBJECTS) $(TYPES_OBJECTS) $(SEMANTIC_OBJECTS) $(UNITTEST_OBJECTS) + $(CC) $(CFLAGS) -o $@ tests/test_labeltable.c runtime/labeltable.c $(IR_OBJECTS) $(TYPES_OBJECTS) $(SEMANTIC_OBJECTS) $(UNITTEST_OBJECTS) $(LDFLAGS) -test_methodcache: tests/test_methodcache.c runtime/methodcache.c runtime/methodcache.h - $(CC) $(CFLAGS) -o $@ tests/test_methodcache.c runtime/methodcache.c $(LDFLAGS) +test_methodcache: tests/test_methodcache.c runtime/methodcache.c runtime/methodcache.h $(UNITTEST_OBJECTS) + $(CC) $(CFLAGS) -o $@ tests/test_methodcache.c runtime/methodcache.c $(UNITTEST_OBJECTS) $(LDFLAGS) test_phase0: test_nanbox test_fastframe test_labeltable test_methodcache @echo "=== Running Phase 0 Tests ===" diff --git a/tests/test_fastframe.c b/tests/test_fastframe.c index e636620..588dcca 100644 --- a/tests/test_fastframe.c +++ b/tests/test_fastframe.c @@ -1,86 +1,93 @@ -#include -#include +#include "test_utils.h" #include "../runtime/fastframe.h" -static int tests_passed = 0; +UnittestTestResult_t* test_init(void) { + UNITTEST_BEGIN_TEST("TestFastFrame", "test_init"); -#define TEST(name) static void test_##name(void) -#define RUN_TEST(name) do { \ - printf("Running %s... ", #name); \ - test_##name(); \ - printf("PASSED\n"); \ - tests_passed++; \ -} while(0) - -TEST(init) { rava_fastframe_init(); - assert(rava_fastframe_get_depth() == 0); - assert(rava_fastframe_current() == NULL); + UNITTEST_ASSERT_EQUAL(_unittest_result, 0, rava_fastframe_get_depth(), "initial depth should be 0"); + UNITTEST_ASSERT_NULL(_unittest_result, rava_fastframe_current(), "current frame should be NULL"); + + UNITTEST_END_TEST(); } -TEST(push_pop) { +UnittestTestResult_t* test_push_pop(void) { + UNITTEST_BEGIN_TEST("TestFastFrame", "test_push_pop"); + rava_fastframe_init(); FastFrame_t* frame = rava_fastframe_push(NULL, 4); - assert(frame != NULL); - assert(rava_fastframe_get_depth() == 1); - assert(rava_fastframe_current() == frame); + UNITTEST_ASSERT_NOT_NULL(_unittest_result, frame, "pushed frame should not be NULL"); + UNITTEST_ASSERT_EQUAL(_unittest_result, 1, rava_fastframe_get_depth(), "depth should be 1"); + UNITTEST_ASSERT_TRUE(_unittest_result, rava_fastframe_current() == frame, "current should match pushed frame"); rava_fastframe_pop(); - assert(rava_fastframe_get_depth() == 0); - assert(rava_fastframe_current() == NULL); + UNITTEST_ASSERT_EQUAL(_unittest_result, 0, rava_fastframe_get_depth(), "depth should be 0 after pop"); + UNITTEST_ASSERT_NULL(_unittest_result, rava_fastframe_current(), "current should be NULL after pop"); + + UNITTEST_END_TEST(); } -TEST(nested_frames) { +UnittestTestResult_t* test_nested_frames(void) { + UNITTEST_BEGIN_TEST("TestFastFrame", "test_nested_frames"); + rava_fastframe_init(); FastFrame_t* f1 = rava_fastframe_push(NULL, 2); FastFrame_t* f2 = rava_fastframe_push(NULL, 2); FastFrame_t* f3 = rava_fastframe_push(NULL, 2); - assert(rava_fastframe_get_depth() == 3); - assert(rava_fastframe_current() == f3); + UNITTEST_ASSERT_EQUAL(_unittest_result, 3, rava_fastframe_get_depth(), "depth should be 3"); + UNITTEST_ASSERT_TRUE(_unittest_result, rava_fastframe_current() == f3, "current should be f3"); rava_fastframe_pop(); - assert(rava_fastframe_current() == f2); + UNITTEST_ASSERT_TRUE(_unittest_result, rava_fastframe_current() == f2, "current should be f2"); rava_fastframe_pop(); - assert(rava_fastframe_current() == f1); + UNITTEST_ASSERT_TRUE(_unittest_result, rava_fastframe_current() == f1, "current should be f1"); rava_fastframe_pop(); - assert(rava_fastframe_current() == NULL); + UNITTEST_ASSERT_NULL(_unittest_result, rava_fastframe_current(), "current should be NULL"); + + UNITTEST_END_TEST(); } -TEST(stack_operations) { +UnittestTestResult_t* test_stack_operations(void) { + UNITTEST_BEGIN_TEST("TestFastFrame", "test_stack_operations"); + rava_fastframe_init(); FastFrame_t* frame = rava_fastframe_push(NULL, 4); - assert(rava_fastframe_stack_is_empty(frame)); + UNITTEST_ASSERT_TRUE(_unittest_result, rava_fastframe_stack_is_empty(frame), "stack should be empty"); rava_fastframe_stack_push(frame, rava_nanbox_int(10)); rava_fastframe_stack_push(frame, rava_nanbox_int(20)); rava_fastframe_stack_push(frame, rava_nanbox_int(30)); - assert(!rava_fastframe_stack_is_empty(frame)); - assert(frame->stack_top == 3); + UNITTEST_ASSERT_FALSE(_unittest_result, rava_fastframe_stack_is_empty(frame), "stack should not be empty"); + UNITTEST_ASSERT_EQUAL(_unittest_result, 3, frame->stack_top, "stack top should be 3"); RavaNanboxValue_t top = rava_fastframe_stack_peek(frame); - assert(rava_nanbox_as_int(top) == 30); - assert(frame->stack_top == 3); + UNITTEST_ASSERT_EQUAL(_unittest_result, 30, rava_nanbox_as_int(top), "peek should return 30"); + UNITTEST_ASSERT_EQUAL(_unittest_result, 3, frame->stack_top, "peek should not change stack top"); RavaNanboxValue_t v1 = rava_fastframe_stack_pop(frame); RavaNanboxValue_t v2 = rava_fastframe_stack_pop(frame); RavaNanboxValue_t v3 = rava_fastframe_stack_pop(frame); - assert(rava_nanbox_as_int(v1) == 30); - assert(rava_nanbox_as_int(v2) == 20); - assert(rava_nanbox_as_int(v3) == 10); - assert(rava_fastframe_stack_is_empty(frame)); + UNITTEST_ASSERT_EQUAL(_unittest_result, 30, rava_nanbox_as_int(v1), "first pop should return 30"); + UNITTEST_ASSERT_EQUAL(_unittest_result, 20, rava_nanbox_as_int(v2), "second pop should return 20"); + UNITTEST_ASSERT_EQUAL(_unittest_result, 10, rava_nanbox_as_int(v3), "third pop should return 10"); + UNITTEST_ASSERT_TRUE(_unittest_result, rava_fastframe_stack_is_empty(frame), "stack should be empty after pops"); rava_fastframe_reset(); + + UNITTEST_END_TEST(); } -TEST(locals) { +UnittestTestResult_t* test_locals(void) { + UNITTEST_BEGIN_TEST("TestFastFrame", "test_locals"); + rava_fastframe_init(); FastFrame_t* frame = rava_fastframe_push(NULL, 8); @@ -89,27 +96,35 @@ TEST(locals) { frame->locals[1] = rava_nanbox_int(200); frame->locals[2] = rava_nanbox_bool(true); - assert(rava_nanbox_as_int(frame->locals[0]) == 100); - assert(rava_nanbox_as_int(frame->locals[1]) == 200); - assert(rava_nanbox_as_bool(frame->locals[2]) == true); + UNITTEST_ASSERT_EQUAL(_unittest_result, 100, rava_nanbox_as_int(frame->locals[0]), "local 0 should be 100"); + UNITTEST_ASSERT_EQUAL(_unittest_result, 200, rava_nanbox_as_int(frame->locals[1]), "local 1 should be 200"); + UNITTEST_ASSERT_TRUE(_unittest_result, rava_nanbox_as_bool(frame->locals[2]), "local 2 should be true"); rava_fastframe_reset(); + + UNITTEST_END_TEST(); } -TEST(reset) { +UnittestTestResult_t* test_reset(void) { + UNITTEST_BEGIN_TEST("TestFastFrame", "test_reset"); + rava_fastframe_init(); rava_fastframe_push(NULL, 2); rava_fastframe_push(NULL, 2); rava_fastframe_push(NULL, 2); - assert(rava_fastframe_get_depth() == 3); + UNITTEST_ASSERT_EQUAL(_unittest_result, 3, rava_fastframe_get_depth(), "depth should be 3"); rava_fastframe_reset(); - assert(rava_fastframe_get_depth() == 0); + UNITTEST_ASSERT_EQUAL(_unittest_result, 0, rava_fastframe_get_depth(), "depth should be 0 after reset"); + + UNITTEST_END_TEST(); } -TEST(stack_clear) { +UnittestTestResult_t* test_stack_clear(void) { + UNITTEST_BEGIN_TEST("TestFastFrame", "test_stack_clear"); + rava_fastframe_init(); FastFrame_t* frame = rava_fastframe_push(NULL, 4); @@ -117,26 +132,43 @@ TEST(stack_clear) { rava_fastframe_stack_push(frame, rava_nanbox_int(2)); rava_fastframe_stack_push(frame, rava_nanbox_int(3)); - assert(frame->stack_top == 3); + UNITTEST_ASSERT_EQUAL(_unittest_result, 3, frame->stack_top, "stack top should be 3"); rava_fastframe_stack_clear(frame); - assert(frame->stack_top == 0); - assert(rava_fastframe_stack_is_empty(frame)); + UNITTEST_ASSERT_EQUAL(_unittest_result, 0, frame->stack_top, "stack top should be 0 after clear"); + UNITTEST_ASSERT_TRUE(_unittest_result, rava_fastframe_stack_is_empty(frame), "stack should be empty after clear"); rava_fastframe_reset(); + + UNITTEST_END_TEST(); } -int main(void) { - printf("=== Fast Frame Unit Tests ===\n\n"); +int main(int argc, char **argv) { + UnittestConfig_t *config = unittest_config_create(); + config->verbosity = 2; - RUN_TEST(init); - RUN_TEST(push_pop); - RUN_TEST(nested_frames); - RUN_TEST(stack_operations); - RUN_TEST(locals); - RUN_TEST(reset); - RUN_TEST(stack_clear); + if (argc > 1 && strcmp(argv[1], "--json") == 0) { + config->output_format = UNITTEST_FORMAT_JSON; + config->use_colors = false; + } - printf("\n=== Results: %d tests passed ===\n", tests_passed); - return 0; + UnittestTestSuite_t *suite = unittest_test_suite_create("Fast Frame Tests"); + + UnittestTestCase_t *tc = unittest_test_case_create("TestFastFrame"); + unittest_test_case_add_result(tc, test_init()); + unittest_test_case_add_result(tc, test_push_pop()); + unittest_test_case_add_result(tc, test_nested_frames()); + unittest_test_case_add_result(tc, test_stack_operations()); + unittest_test_case_add_result(tc, test_locals()); + unittest_test_case_add_result(tc, test_reset()); + unittest_test_case_add_result(tc, test_stack_clear()); + unittest_test_suite_add_test_case(suite, tc); + + unittest_generate_report(suite, config); + + int failures = suite->total_failed + suite->total_errors; + unittest_test_suite_destroy(suite); + unittest_config_destroy(config); + + return failures > 0 ? 1 : 0; } diff --git a/tests/test_labeltable.c b/tests/test_labeltable.c index d63419b..4377286 100644 --- a/tests/test_labeltable.c +++ b/tests/test_labeltable.c @@ -1,33 +1,31 @@ -#include -#include -#include +#include "test_utils.h" #include "../ir/ir.h" #include "../runtime/labeltable.h" -static int tests_passed = 0; +UnittestTestResult_t* test_create_empty(void) { + UNITTEST_BEGIN_TEST("TestLabelTable", "test_create_empty"); -#define TEST(name) static void test_##name(void) -#define RUN_TEST(name) do { \ - printf("Running %s... ", #name); \ - test_##name(); \ - printf("PASSED\n"); \ - tests_passed++; \ -} while(0) - -TEST(create_empty) { RavaInstructionList_t* list = rava_instruction_list_create(); LabelTable_t* table = rava_labeltable_create(list); - assert(table != NULL); + UNITTEST_ASSERT_NOT_NULL(_unittest_result, table, "table should not be NULL"); rava_labeltable_destroy(table); rava_instruction_list_destroy(list); + + UNITTEST_END_TEST(); } -TEST(create_null) { +UnittestTestResult_t* test_create_null(void) { + UNITTEST_BEGIN_TEST("TestLabelTable", "test_create_null"); + LabelTable_t* table = rava_labeltable_create(NULL); - assert(table == NULL); + UNITTEST_ASSERT_NULL(_unittest_result, table, "table should be NULL for NULL input"); + + UNITTEST_END_TEST(); } -TEST(single_label) { +UnittestTestResult_t* test_single_label(void) { + UNITTEST_BEGIN_TEST("TestLabelTable", "test_single_label"); + RavaInstructionList_t* list = rava_instruction_list_create(); RavaInstruction_t instr1 = {.opcode = RAVA_OP_LOAD_CONST, .operand.int_value = 10}; @@ -39,16 +37,20 @@ TEST(single_label) { rava_instruction_list_add(list, instr3); LabelTable_t* table = rava_labeltable_create(list); - assert(table != NULL); + UNITTEST_ASSERT_NOT_NULL(_unittest_result, table, "table should not be NULL"); size_t pc = rava_labeltable_lookup(table, 0); - assert(pc == 2); + UNITTEST_ASSERT_EQUAL(_unittest_result, 2, (int)pc, "label 0 should point to PC 2"); rava_labeltable_destroy(table); rava_instruction_list_destroy(list); + + UNITTEST_END_TEST(); } -TEST(multiple_labels) { +UnittestTestResult_t* test_multiple_labels(void) { + UNITTEST_BEGIN_TEST("TestLabelTable", "test_multiple_labels"); + RavaInstructionList_t* list = rava_instruction_list_create(); RavaInstruction_t instr0 = {.opcode = RAVA_OP_LOAD_CONST, .operand.int_value = 0}; @@ -66,59 +68,84 @@ TEST(multiple_labels) { rava_instruction_list_add(list, label2); LabelTable_t* table = rava_labeltable_create(list); - assert(table != NULL); + UNITTEST_ASSERT_NOT_NULL(_unittest_result, table, "table should not be NULL"); - assert(rava_labeltable_lookup(table, 0) == 2); - assert(rava_labeltable_lookup(table, 1) == 4); - assert(rava_labeltable_lookup(table, 2) == 6); + UNITTEST_ASSERT_EQUAL(_unittest_result, 2, (int)rava_labeltable_lookup(table, 0), "label 0 should point to PC 2"); + UNITTEST_ASSERT_EQUAL(_unittest_result, 4, (int)rava_labeltable_lookup(table, 1), "label 1 should point to PC 4"); + UNITTEST_ASSERT_EQUAL(_unittest_result, 6, (int)rava_labeltable_lookup(table, 2), "label 2 should point to PC 6"); rava_labeltable_destroy(table); rava_instruction_list_destroy(list); + + UNITTEST_END_TEST(); } -TEST(missing_label) { +UnittestTestResult_t* test_missing_label(void) { + UNITTEST_BEGIN_TEST("TestLabelTable", "test_missing_label"); + RavaInstructionList_t* list = rava_instruction_list_create(); RavaInstruction_t label = {.opcode = RAVA_OP_LABEL, .operand.label_id = 5}; rava_instruction_list_add(list, label); LabelTable_t* table = rava_labeltable_create(list); - assert(table != NULL); + UNITTEST_ASSERT_NOT_NULL(_unittest_result, table, "table should not be NULL"); - assert(rava_labeltable_lookup(table, 0) == 0); - assert(rava_labeltable_lookup(table, 1) == 0); - assert(rava_labeltable_lookup(table, 5) == 1); + UNITTEST_ASSERT_EQUAL(_unittest_result, 0, (int)rava_labeltable_lookup(table, 0), "missing label 0 should return 0"); + UNITTEST_ASSERT_EQUAL(_unittest_result, 0, (int)rava_labeltable_lookup(table, 1), "missing label 1 should return 0"); + UNITTEST_ASSERT_EQUAL(_unittest_result, 1, (int)rava_labeltable_lookup(table, 5), "label 5 should point to PC 1"); rava_labeltable_destroy(table); rava_instruction_list_destroy(list); + + UNITTEST_END_TEST(); } -TEST(out_of_range) { +UnittestTestResult_t* test_out_of_range(void) { + UNITTEST_BEGIN_TEST("TestLabelTable", "test_out_of_range"); + RavaInstructionList_t* list = rava_instruction_list_create(); RavaInstruction_t label = {.opcode = RAVA_OP_LABEL, .operand.label_id = 2}; rava_instruction_list_add(list, label); LabelTable_t* table = rava_labeltable_create(list); - assert(table != NULL); + UNITTEST_ASSERT_NOT_NULL(_unittest_result, table, "table should not be NULL"); - assert(rava_labeltable_lookup(table, 100) == 0); - assert(rava_labeltable_lookup(table, -1) == 0); + UNITTEST_ASSERT_EQUAL(_unittest_result, 0, (int)rava_labeltable_lookup(table, 100), "out of range label should return 0"); + UNITTEST_ASSERT_EQUAL(_unittest_result, 0, (int)rava_labeltable_lookup(table, -1), "negative label should return 0"); rava_labeltable_destroy(table); rava_instruction_list_destroy(list); + + UNITTEST_END_TEST(); } -int main(void) { - printf("=== Label Table Unit Tests ===\n\n"); +int main(int argc, char **argv) { + UnittestConfig_t *config = unittest_config_create(); + config->verbosity = 2; - RUN_TEST(create_empty); - RUN_TEST(create_null); - RUN_TEST(single_label); - RUN_TEST(multiple_labels); - RUN_TEST(missing_label); - RUN_TEST(out_of_range); + if (argc > 1 && strcmp(argv[1], "--json") == 0) { + config->output_format = UNITTEST_FORMAT_JSON; + config->use_colors = false; + } - printf("\n=== Results: %d tests passed ===\n", tests_passed); - return 0; + UnittestTestSuite_t *suite = unittest_test_suite_create("Label Table Tests"); + + UnittestTestCase_t *tc = unittest_test_case_create("TestLabelTable"); + unittest_test_case_add_result(tc, test_create_empty()); + unittest_test_case_add_result(tc, test_create_null()); + unittest_test_case_add_result(tc, test_single_label()); + unittest_test_case_add_result(tc, test_multiple_labels()); + unittest_test_case_add_result(tc, test_missing_label()); + unittest_test_case_add_result(tc, test_out_of_range()); + unittest_test_suite_add_test_case(suite, tc); + + unittest_generate_report(suite, config); + + int failures = suite->total_failed + suite->total_errors; + unittest_test_suite_destroy(suite); + unittest_config_destroy(config); + + return failures > 0 ? 1 : 0; } diff --git a/tests/test_methodcache.c b/tests/test_methodcache.c index 53d81ca..89bf65c 100644 --- a/tests/test_methodcache.c +++ b/tests/test_methodcache.c @@ -1,26 +1,21 @@ -#include -#include +#include "test_utils.h" #include "../runtime/methodcache.h" -static int tests_passed = 0; +UnittestTestResult_t* test_create_destroy(void) { + UNITTEST_BEGIN_TEST("TestMethodCache", "test_create_destroy"); -#define TEST(name) static void test_##name(void) -#define RUN_TEST(name) do { \ - printf("Running %s... ", #name); \ - test_##name(); \ - printf("PASSED\n"); \ - tests_passed++; \ -} while(0) - -TEST(create_destroy) { MethodCache_t* cache = rava_methodcache_create(); - assert(cache != NULL); + UNITTEST_ASSERT_NOT_NULL(_unittest_result, cache, "cache should not be NULL"); rava_methodcache_destroy(cache); + + UNITTEST_END_TEST(); } -TEST(insert_lookup) { +UnittestTestResult_t* test_insert_lookup(void) { + UNITTEST_BEGIN_TEST("TestMethodCache", "test_insert_lookup"); + MethodCache_t* cache = rava_methodcache_create(); - assert(cache != NULL); + UNITTEST_ASSERT_NOT_NULL(_unittest_result, cache, "cache should not be NULL"); int dummy_method = 42; RavaMethod_t* method = (RavaMethod_t*)&dummy_method; @@ -28,24 +23,32 @@ TEST(insert_lookup) { rava_methodcache_insert(cache, "TestClass", "testMethod", method); RavaMethod_t* found = rava_methodcache_lookup(cache, "TestClass", "testMethod"); - assert(found == method); + UNITTEST_ASSERT_TRUE(_unittest_result, found == method, "found method should match inserted"); rava_methodcache_destroy(cache); + + UNITTEST_END_TEST(); } -TEST(lookup_miss) { +UnittestTestResult_t* test_lookup_miss(void) { + UNITTEST_BEGIN_TEST("TestMethodCache", "test_lookup_miss"); + MethodCache_t* cache = rava_methodcache_create(); - assert(cache != NULL); + UNITTEST_ASSERT_NOT_NULL(_unittest_result, cache, "cache should not be NULL"); RavaMethod_t* found = rava_methodcache_lookup(cache, "NonExistent", "method"); - assert(found == NULL); + UNITTEST_ASSERT_NULL(_unittest_result, found, "lookup miss should return NULL"); rava_methodcache_destroy(cache); + + UNITTEST_END_TEST(); } -TEST(multiple_methods) { +UnittestTestResult_t* test_multiple_methods(void) { + UNITTEST_BEGIN_TEST("TestMethodCache", "test_multiple_methods"); + MethodCache_t* cache = rava_methodcache_create(); - assert(cache != NULL); + UNITTEST_ASSERT_NOT_NULL(_unittest_result, cache, "cache should not be NULL"); int m1 = 1, m2 = 2; RavaMethod_t* method1 = (RavaMethod_t*)&m1; @@ -53,67 +56,96 @@ TEST(multiple_methods) { rava_methodcache_insert(cache, "TestClass", "methodA", method1); RavaMethod_t* found1 = rava_methodcache_lookup(cache, "TestClass", "methodA"); - assert(found1 == method1); + UNITTEST_ASSERT_TRUE(_unittest_result, found1 == method1, "found1 should match method1"); rava_methodcache_insert(cache, "OtherClass", "methodB", method2); RavaMethod_t* found2 = rava_methodcache_lookup(cache, "OtherClass", "methodB"); - assert(found2 == method2); + UNITTEST_ASSERT_TRUE(_unittest_result, found2 == method2, "found2 should match method2"); rava_methodcache_destroy(cache); + + UNITTEST_END_TEST(); } -TEST(clear) { +UnittestTestResult_t* test_clear(void) { + UNITTEST_BEGIN_TEST("TestMethodCache", "test_clear"); + MethodCache_t* cache = rava_methodcache_create(); - assert(cache != NULL); + UNITTEST_ASSERT_NOT_NULL(_unittest_result, cache, "cache should not be NULL"); int dummy = 42; RavaMethod_t* method = (RavaMethod_t*)&dummy; rava_methodcache_insert(cache, "TestClass", "testMethod", method); - assert(rava_methodcache_lookup(cache, "TestClass", "testMethod") == method); + UNITTEST_ASSERT_TRUE(_unittest_result, rava_methodcache_lookup(cache, "TestClass", "testMethod") == method, "should find method before clear"); rava_methodcache_clear(cache); - assert(rava_methodcache_lookup(cache, "TestClass", "testMethod") == NULL); + UNITTEST_ASSERT_NULL(_unittest_result, rava_methodcache_lookup(cache, "TestClass", "testMethod"), "should not find method after clear"); rava_methodcache_destroy(cache); + + UNITTEST_END_TEST(); } -TEST(null_params) { +UnittestTestResult_t* test_null_params(void) { + UNITTEST_BEGIN_TEST("TestMethodCache", "test_null_params"); + MethodCache_t* cache = rava_methodcache_create(); rava_methodcache_insert(NULL, "Class", "method", NULL); rava_methodcache_insert(cache, NULL, "method", NULL); rava_methodcache_insert(cache, "Class", NULL, NULL); - assert(rava_methodcache_lookup(NULL, "Class", "method") == NULL); - assert(rava_methodcache_lookup(cache, NULL, "method") == NULL); - assert(rava_methodcache_lookup(cache, "Class", NULL) == NULL); + UNITTEST_ASSERT_NULL(_unittest_result, rava_methodcache_lookup(NULL, "Class", "method"), "NULL cache should return NULL"); + UNITTEST_ASSERT_NULL(_unittest_result, rava_methodcache_lookup(cache, NULL, "method"), "NULL class should return NULL"); + UNITTEST_ASSERT_NULL(_unittest_result, rava_methodcache_lookup(cache, "Class", NULL), "NULL method should return NULL"); rava_methodcache_destroy(cache); + + UNITTEST_END_TEST(); } -TEST(hash_function) { +UnittestTestResult_t* test_hash_function(void) { + UNITTEST_BEGIN_TEST("TestMethodCache", "test_hash_function"); + uint32_t h1 = rava_methodcache_hash("hello"); uint32_t h2 = rava_methodcache_hash("hello"); uint32_t h3 = rava_methodcache_hash("world"); - assert(h1 == h2); - assert(h1 != h3); - assert(h1 != 0); - assert(h3 != 0); + UNITTEST_ASSERT_EQUAL(_unittest_result, h1, h2, "same string should produce same hash"); + UNITTEST_ASSERT_TRUE(_unittest_result, h1 != h3, "different strings should produce different hashes"); + UNITTEST_ASSERT_TRUE(_unittest_result, h1 != 0, "hash should not be 0"); + UNITTEST_ASSERT_TRUE(_unittest_result, h3 != 0, "hash should not be 0"); + + UNITTEST_END_TEST(); } -int main(void) { - printf("=== Method Cache Unit Tests ===\n\n"); +int main(int argc, char **argv) { + UnittestConfig_t *config = unittest_config_create(); + config->verbosity = 2; - RUN_TEST(create_destroy); - RUN_TEST(insert_lookup); - RUN_TEST(lookup_miss); - RUN_TEST(multiple_methods); - RUN_TEST(clear); - RUN_TEST(null_params); - RUN_TEST(hash_function); + if (argc > 1 && strcmp(argv[1], "--json") == 0) { + config->output_format = UNITTEST_FORMAT_JSON; + config->use_colors = false; + } - printf("\n=== Results: %d tests passed ===\n", tests_passed); - return 0; + UnittestTestSuite_t *suite = unittest_test_suite_create("Method Cache Tests"); + + UnittestTestCase_t *tc = unittest_test_case_create("TestMethodCache"); + unittest_test_case_add_result(tc, test_create_destroy()); + unittest_test_case_add_result(tc, test_insert_lookup()); + unittest_test_case_add_result(tc, test_lookup_miss()); + unittest_test_case_add_result(tc, test_multiple_methods()); + unittest_test_case_add_result(tc, test_clear()); + unittest_test_case_add_result(tc, test_null_params()); + unittest_test_case_add_result(tc, test_hash_function()); + unittest_test_suite_add_test_case(suite, tc); + + unittest_generate_report(suite, config); + + int failures = suite->total_failed + suite->total_errors; + unittest_test_suite_destroy(suite); + unittest_config_destroy(config); + + return failures > 0 ? 1 : 0; } diff --git a/tests/test_nanbox.c b/tests/test_nanbox.c index 2897b4f..a1f7640 100644 --- a/tests/test_nanbox.c +++ b/tests/test_nanbox.c @@ -1,146 +1,211 @@ -#include -#include +#include "test_utils.h" #include #include "../runtime/nanbox.h" -static int tests_passed = 0; -static int tests_failed = 0; +UnittestTestResult_t* test_int_basic(void) { + UNITTEST_BEGIN_TEST("TestNanbox", "test_int_basic"); -#define TEST(name) static void test_##name(void) -#define RUN_TEST(name) do { \ - printf("Running %s... ", #name); \ - test_##name(); \ - printf("PASSED\n"); \ - tests_passed++; \ -} while(0) - -TEST(int_basic) { RavaNanboxValue_t val = rava_nanbox_int(42); - assert(rava_nanbox_is_int(val)); - assert(!rava_nanbox_is_bool(val)); - assert(!rava_nanbox_is_null(val)); - assert(rava_nanbox_as_int(val) == 42); + UNITTEST_ASSERT_TRUE(_unittest_result, rava_nanbox_is_int(val), "should be int"); + UNITTEST_ASSERT_FALSE(_unittest_result, rava_nanbox_is_bool(val), "should not be bool"); + UNITTEST_ASSERT_FALSE(_unittest_result, rava_nanbox_is_null(val), "should not be null"); + UNITTEST_ASSERT_EQUAL(_unittest_result, 42, rava_nanbox_as_int(val), "should equal 42"); + + UNITTEST_END_TEST(); } -TEST(int_negative) { +UnittestTestResult_t* test_int_negative(void) { + UNITTEST_BEGIN_TEST("TestNanbox", "test_int_negative"); + RavaNanboxValue_t val = rava_nanbox_int(-100); - assert(rava_nanbox_is_int(val)); - assert(rava_nanbox_as_int(val) == -100); + UNITTEST_ASSERT_TRUE(_unittest_result, rava_nanbox_is_int(val), "should be int"); + UNITTEST_ASSERT_EQUAL(_unittest_result, -100, rava_nanbox_as_int(val), "should equal -100"); + + UNITTEST_END_TEST(); } -TEST(int_zero) { +UnittestTestResult_t* test_int_zero(void) { + UNITTEST_BEGIN_TEST("TestNanbox", "test_int_zero"); + RavaNanboxValue_t val = rava_nanbox_int(0); - assert(rava_nanbox_is_int(val)); - assert(rava_nanbox_as_int(val) == 0); + UNITTEST_ASSERT_TRUE(_unittest_result, rava_nanbox_is_int(val), "should be int"); + UNITTEST_ASSERT_EQUAL(_unittest_result, 0, rava_nanbox_as_int(val), "should equal 0"); + + UNITTEST_END_TEST(); } -TEST(long_basic) { +UnittestTestResult_t* test_long_basic(void) { + UNITTEST_BEGIN_TEST("TestNanbox", "test_long_basic"); + RavaNanboxValue_t val = rava_nanbox_long(1000000000000LL); - assert(rava_nanbox_is_long(val)); - int64_t result = rava_nanbox_as_long(val); - (void)result; + UNITTEST_ASSERT_TRUE(_unittest_result, rava_nanbox_is_long(val), "should be long"); + + UNITTEST_END_TEST(); } -TEST(bool_true) { +UnittestTestResult_t* test_bool_true(void) { + UNITTEST_BEGIN_TEST("TestNanbox", "test_bool_true"); + RavaNanboxValue_t val = rava_nanbox_bool(true); - assert(rava_nanbox_is_bool(val)); - assert(rava_nanbox_as_bool(val) == true); + UNITTEST_ASSERT_TRUE(_unittest_result, rava_nanbox_is_bool(val), "should be bool"); + UNITTEST_ASSERT_TRUE(_unittest_result, rava_nanbox_as_bool(val), "should be true"); + + UNITTEST_END_TEST(); } -TEST(bool_false) { +UnittestTestResult_t* test_bool_false(void) { + UNITTEST_BEGIN_TEST("TestNanbox", "test_bool_false"); + RavaNanboxValue_t val = rava_nanbox_bool(false); - assert(rava_nanbox_is_bool(val)); - assert(rava_nanbox_as_bool(val) == false); + UNITTEST_ASSERT_TRUE(_unittest_result, rava_nanbox_is_bool(val), "should be bool"); + UNITTEST_ASSERT_FALSE(_unittest_result, rava_nanbox_as_bool(val), "should be false"); + + UNITTEST_END_TEST(); } -TEST(null) { +UnittestTestResult_t* test_null(void) { + UNITTEST_BEGIN_TEST("TestNanbox", "test_null"); + RavaNanboxValue_t val = rava_nanbox_null(); - assert(rava_nanbox_is_null(val)); - assert(!rava_nanbox_is_int(val)); - assert(!rava_nanbox_is_bool(val)); + UNITTEST_ASSERT_TRUE(_unittest_result, rava_nanbox_is_null(val), "should be null"); + UNITTEST_ASSERT_FALSE(_unittest_result, rava_nanbox_is_int(val), "should not be int"); + UNITTEST_ASSERT_FALSE(_unittest_result, rava_nanbox_is_bool(val), "should not be bool"); + + UNITTEST_END_TEST(); } -TEST(double_basic) { +UnittestTestResult_t* test_double_basic(void) { + UNITTEST_BEGIN_TEST("TestNanbox", "test_double_basic"); + RavaNanboxValue_t val = rava_nanbox_double(3.14159); - assert(rava_nanbox_is_double(val)); + UNITTEST_ASSERT_TRUE(_unittest_result, rava_nanbox_is_double(val), "should be double"); double d = rava_nanbox_as_double(val); - assert(fabs(d - 3.14159) < 0.0001); + UNITTEST_ASSERT_TRUE(_unittest_result, fabs(d - 3.14159) < 0.0001, "should equal 3.14159"); + + UNITTEST_END_TEST(); } -TEST(double_negative) { +UnittestTestResult_t* test_double_negative(void) { + UNITTEST_BEGIN_TEST("TestNanbox", "test_double_negative"); + RavaNanboxValue_t val = rava_nanbox_double(-123.456); - assert(rava_nanbox_is_double(val)); + UNITTEST_ASSERT_TRUE(_unittest_result, rava_nanbox_is_double(val), "should be double"); double d = rava_nanbox_as_double(val); - assert(fabs(d - (-123.456)) < 0.0001); + UNITTEST_ASSERT_TRUE(_unittest_result, fabs(d - (-123.456)) < 0.0001, "should equal -123.456"); + + UNITTEST_END_TEST(); } -TEST(conversion_int_to_long) { +UnittestTestResult_t* test_conversion_int_to_long(void) { + UNITTEST_BEGIN_TEST("TestNanbox", "test_conversion_int_to_long"); + RavaNanboxValue_t val = rava_nanbox_int(42); - assert(rava_nanbox_to_long(val) == 42); + UNITTEST_ASSERT_EQUAL(_unittest_result, 42, (int)rava_nanbox_to_long(val), "int to long should equal 42"); + + UNITTEST_END_TEST(); } -TEST(conversion_int_to_double) { +UnittestTestResult_t* test_conversion_int_to_double(void) { + UNITTEST_BEGIN_TEST("TestNanbox", "test_conversion_int_to_double"); + RavaNanboxValue_t val = rava_nanbox_int(10); - assert(fabs(rava_nanbox_to_double(val) - 10.0) < 0.0001); + UNITTEST_ASSERT_TRUE(_unittest_result, fabs(rava_nanbox_to_double(val) - 10.0) < 0.0001, "int to double should equal 10.0"); + + UNITTEST_END_TEST(); } -TEST(conversion_bool_to_int) { +UnittestTestResult_t* test_conversion_bool_to_int(void) { + UNITTEST_BEGIN_TEST("TestNanbox", "test_conversion_bool_to_int"); + RavaNanboxValue_t t = rava_nanbox_bool(true); RavaNanboxValue_t f = rava_nanbox_bool(false); - assert(rava_nanbox_to_int(t) == 1); - assert(rava_nanbox_to_int(f) == 0); + UNITTEST_ASSERT_EQUAL(_unittest_result, 1, rava_nanbox_to_int(t), "true to int should equal 1"); + UNITTEST_ASSERT_EQUAL(_unittest_result, 0, rava_nanbox_to_int(f), "false to int should equal 0"); + + UNITTEST_END_TEST(); } -TEST(to_bool) { - assert(rava_nanbox_to_bool(rava_nanbox_null()) == false); - assert(rava_nanbox_to_bool(rava_nanbox_bool(true)) == true); - assert(rava_nanbox_to_bool(rava_nanbox_bool(false)) == false); - assert(rava_nanbox_to_bool(rava_nanbox_int(0)) == false); - assert(rava_nanbox_to_bool(rava_nanbox_int(1)) == true); - assert(rava_nanbox_to_bool(rava_nanbox_int(-1)) == true); +UnittestTestResult_t* test_to_bool(void) { + UNITTEST_BEGIN_TEST("TestNanbox", "test_to_bool"); + + UNITTEST_ASSERT_FALSE(_unittest_result, rava_nanbox_to_bool(rava_nanbox_null()), "null to bool should be false"); + UNITTEST_ASSERT_TRUE(_unittest_result, rava_nanbox_to_bool(rava_nanbox_bool(true)), "true to bool should be true"); + UNITTEST_ASSERT_FALSE(_unittest_result, rava_nanbox_to_bool(rava_nanbox_bool(false)), "false to bool should be false"); + UNITTEST_ASSERT_FALSE(_unittest_result, rava_nanbox_to_bool(rava_nanbox_int(0)), "0 to bool should be false"); + UNITTEST_ASSERT_TRUE(_unittest_result, rava_nanbox_to_bool(rava_nanbox_int(1)), "1 to bool should be true"); + UNITTEST_ASSERT_TRUE(_unittest_result, rava_nanbox_to_bool(rava_nanbox_int(-1)), "-1 to bool should be true"); + + UNITTEST_END_TEST(); } -TEST(object_pointer) { +UnittestTestResult_t* test_object_pointer(void) { + UNITTEST_BEGIN_TEST("TestNanbox", "test_object_pointer"); + int dummy = 42; RavaNanboxValue_t val = rava_nanbox_object(&dummy); - assert(rava_nanbox_is_object(val)); - assert(rava_nanbox_as_object(val) == &dummy); + UNITTEST_ASSERT_TRUE(_unittest_result, rava_nanbox_is_object(val), "should be object"); + UNITTEST_ASSERT_TRUE(_unittest_result, rava_nanbox_as_object(val) == &dummy, "pointer should match"); + + UNITTEST_END_TEST(); } -TEST(string_pointer) { +UnittestTestResult_t* test_string_pointer(void) { + UNITTEST_BEGIN_TEST("TestNanbox", "test_string_pointer"); + const char* str = "hello"; RavaNanboxValue_t val = rava_nanbox_string(str); - assert(rava_nanbox_is_string(val)); - assert(rava_nanbox_as_string(val) == str); + UNITTEST_ASSERT_TRUE(_unittest_result, rava_nanbox_is_string(val), "should be string"); + UNITTEST_ASSERT_TRUE(_unittest_result, rava_nanbox_as_string(val) == str, "pointer should match"); + + UNITTEST_END_TEST(); } -TEST(array_pointer) { +UnittestTestResult_t* test_array_pointer(void) { + UNITTEST_BEGIN_TEST("TestNanbox", "test_array_pointer"); + int arr[10]; RavaNanboxValue_t val = rava_nanbox_array(arr); - assert(rava_nanbox_is_array(val)); - assert(rava_nanbox_as_array(val) == arr); + UNITTEST_ASSERT_TRUE(_unittest_result, rava_nanbox_is_array(val), "should be array"); + UNITTEST_ASSERT_TRUE(_unittest_result, rava_nanbox_as_array(val) == arr, "pointer should match"); + + UNITTEST_END_TEST(); } -int main(void) { - printf("=== NaN Boxing Unit Tests ===\n\n"); +int main(int argc, char **argv) { + UnittestConfig_t *config = unittest_config_create(); + config->verbosity = 2; - RUN_TEST(int_basic); - RUN_TEST(int_negative); - RUN_TEST(int_zero); - RUN_TEST(long_basic); - RUN_TEST(bool_true); - RUN_TEST(bool_false); - RUN_TEST(null); - RUN_TEST(double_basic); - RUN_TEST(double_negative); - RUN_TEST(conversion_int_to_long); - RUN_TEST(conversion_int_to_double); - RUN_TEST(conversion_bool_to_int); - RUN_TEST(to_bool); - RUN_TEST(object_pointer); - RUN_TEST(string_pointer); - RUN_TEST(array_pointer); + if (argc > 1 && strcmp(argv[1], "--json") == 0) { + config->output_format = UNITTEST_FORMAT_JSON; + config->use_colors = false; + } - printf("\n=== Results: %d passed, %d failed ===\n", tests_passed, tests_failed); - return tests_failed > 0 ? 1 : 0; + UnittestTestSuite_t *suite = unittest_test_suite_create("NaN Boxing Tests"); + + UnittestTestCase_t *tc = unittest_test_case_create("TestNanbox"); + unittest_test_case_add_result(tc, test_int_basic()); + unittest_test_case_add_result(tc, test_int_negative()); + unittest_test_case_add_result(tc, test_int_zero()); + unittest_test_case_add_result(tc, test_long_basic()); + unittest_test_case_add_result(tc, test_bool_true()); + unittest_test_case_add_result(tc, test_bool_false()); + unittest_test_case_add_result(tc, test_null()); + unittest_test_case_add_result(tc, test_double_basic()); + unittest_test_case_add_result(tc, test_double_negative()); + unittest_test_case_add_result(tc, test_conversion_int_to_long()); + unittest_test_case_add_result(tc, test_conversion_int_to_double()); + unittest_test_case_add_result(tc, test_conversion_bool_to_int()); + unittest_test_case_add_result(tc, test_to_bool()); + unittest_test_case_add_result(tc, test_object_pointer()); + unittest_test_case_add_result(tc, test_string_pointer()); + unittest_test_case_add_result(tc, test_array_pointer()); + unittest_test_suite_add_test_case(suite, tc); + + unittest_generate_report(suite, config); + + int failures = suite->total_failed + suite->total_errors; + unittest_test_suite_destroy(suite); + unittest_config_destroy(config); + + return failures > 0 ? 1 : 0; } diff --git a/tests/unittest.h b/tests/unittest.h index 9858807..a09fbc9 100644 --- a/tests/unittest.h +++ b/tests/unittest.h @@ -168,6 +168,9 @@ void _unittest_format_tap(UnittestTestSuite_t *suite, UnittestConfig_t *config, double unittest_get_time_ms(void); +#define UNITTEST_ASSERT_EQUAL(result, expected, actual, msg) \ + unittest_assert_int_equal((result), (expected), (actual), (msg), __LINE__, __FILE__) + #define UNITTEST_ASSERT_EQUAL_INT(result, expected, actual, msg) \ unittest_assert_int_equal((result), (expected), (actual), (msg), __LINE__, __FILE__)