#include "../lexer/lexer.h" #include "../parser/parser.h" #include "../semantic/semantic.h" #include "../ir/ir.h" #include "../ir/ir_gen.h" #include "../runtime/runtime.h" #include #include #include typedef enum { EXPECT_PARSE_ERROR, EXPECT_SEMANTIC_ERROR, EXPECT_RUNTIME_ERROR, EXPECT_MISSING_CLASS, EXPECT_MISSING_METHOD } ExpectedError_e; static bool test_error(const char *name, const char *source, ExpectedError_e expected, const char *exec_class, const char *exec_method) { printf("Test: %-40s ... ", name); fflush(stdout); if (!source || strlen(source) == 0) { printf("PASS (skipped empty input)\n"); return true; } RavaLexer_t *lexer = rava_lexer_create(source); if (!lexer) { bool success = (expected == EXPECT_PARSE_ERROR); printf("%s\n", success ? "PASS" : "FAIL"); return success; } RavaParser_t *parser = rava_parser_create(lexer); RavaASTNode_t *ast = rava_parser_parse(parser); if (parser->had_error) { bool success = (expected == EXPECT_PARSE_ERROR); printf("%s\n", success ? "PASS" : "FAIL"); rava_parser_destroy(parser); rava_lexer_destroy(lexer); return success; } if (expected == EXPECT_PARSE_ERROR) { printf("FAIL (expected parse error)\n"); rava_ast_node_destroy(ast); rava_parser_destroy(parser); rava_lexer_destroy(lexer); return false; } RavaSemanticAnalyzer_t *analyzer = rava_semantic_analyzer_create(); if (!rava_semantic_analyze(analyzer, ast)) { bool success = (expected == EXPECT_SEMANTIC_ERROR); printf("%s\n", success ? "PASS" : "FAIL"); rava_semantic_analyzer_destroy(analyzer); rava_ast_node_destroy(ast); rava_parser_destroy(parser); rava_lexer_destroy(lexer); return success; } if (expected == EXPECT_SEMANTIC_ERROR) { printf("FAIL (expected semantic error)\n"); rava_semantic_analyzer_destroy(analyzer); rava_ast_node_destroy(ast); rava_parser_destroy(parser); rava_lexer_destroy(lexer); return false; } RavaIRGenerator_t *ir_gen = rava_ir_generator_create(analyzer); RavaProgram_t *program = rava_ir_generate(ir_gen, ast); if (!program) { bool success = (expected == EXPECT_RUNTIME_ERROR); printf("%s\n", success ? "PASS" : "FAIL"); rava_ir_generator_destroy(ir_gen); rava_semantic_analyzer_destroy(analyzer); rava_ast_node_destroy(ast); rava_parser_destroy(parser); rava_lexer_destroy(lexer); return success; } RavaVM_t *vm = rava_vm_create(program); if (!rava_vm_execute(vm, exec_class, exec_method)) { bool success = (expected == EXPECT_RUNTIME_ERROR || expected == EXPECT_MISSING_CLASS || expected == EXPECT_MISSING_METHOD); printf("%s\n", success ? "PASS" : "FAIL"); rava_vm_destroy(vm); rava_program_destroy(program); rava_ir_generator_destroy(ir_gen); rava_semantic_analyzer_destroy(analyzer); rava_ast_node_destroy(ast); rava_parser_destroy(parser); rava_lexer_destroy(lexer); return success; } printf("FAIL (expected error)\n"); rava_vm_destroy(vm); rava_program_destroy(program); rava_ir_generator_destroy(ir_gen); rava_semantic_analyzer_destroy(analyzer); rava_ast_node_destroy(ast); rava_parser_destroy(parser); rava_lexer_destroy(lexer); return false; } int main(void) { printf("=== NEGATIVE TEST CASES ===\n\n"); int passed = 0; int total = 0; total++; if (test_error("Missing class body", "public class Test", EXPECT_PARSE_ERROR, "Test", "main")) { passed++; } total++; if (test_error("Missing method body", "public class Test {\n" " public static int main()\n" "}\n", EXPECT_PARSE_ERROR, "Test", "main")) { passed++; } total++; if (test_error("Unclosed brace", "public class Test {\n" " public static int main() {\n" " return 0;\n" "}\n", EXPECT_PARSE_ERROR, "Test", "main")) { passed++; } total++; if (test_error("Missing semicolon", "public class Test {\n" " public static int main() {\n" " int x = 5\n" " return x;\n" " }\n" "}\n", EXPECT_PARSE_ERROR, "Test", "main")) { passed++; } total++; if (test_error("Undefined variable", "public class Test {\n" " public static int main() {\n" " return undefinedVar;\n" " }\n" "}\n", EXPECT_SEMANTIC_ERROR, "Test", "main")) { passed++; } total++; if (test_error("Undefined method call", "public class Test {\n" " public static int main() {\n" " return undefinedMethod();\n" " }\n" "}\n", EXPECT_SEMANTIC_ERROR, "Test", "main")) { passed++; } total++; if (test_error("Missing class at runtime", "public class Test {\n" " public static int main() {\n" " return 0;\n" " }\n" "}\n", EXPECT_MISSING_CLASS, "NonExistent", "main")) { passed++; } total++; if (test_error("Missing method at runtime", "public class Test {\n" " public static int main() {\n" " return 0;\n" " }\n" "}\n", EXPECT_MISSING_METHOD, "Test", "nonExistent")) { passed++; } total++; if (test_error("Duplicate variable", "public class Test {\n" " public static int main() {\n" " int x = 5;\n" " int x = 10;\n" " return x;\n" " }\n" "}\n", EXPECT_SEMANTIC_ERROR, "Test", "main")) { passed++; } total++; if (test_error("Malformed for loop", "public class Test {\n" " public static int main() {\n" " for (int i = 0; i < 10) {\n" " }\n" " return 0;\n" " }\n" "}\n", EXPECT_PARSE_ERROR, "Test", "main")) { passed++; } printf("\n=== Results: %d/%d tests passed ===\n", passed, total); return (passed == total) ? 0 : 1; }