#!/bin/bash # CCDJIT Comprehensive Test Runner # This script provides a more advanced testing interface with better organization # Colors for pretty output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' PURPLE='\033[0;35m' CYAN='\033[0;36m' WHITE='\033[1;37m' GRAY='\033[0;37m' NC='\033[0m' # No Color # Test configuration declare -A test_map test_map["./tests/add2.c"]=3 test_map["./tests/arithmetic.c"]=28 test_map["./tests/comparison.c"]=5 test_map["./tests/logical.c"]=3 test_map["./tests/if_else.c"]=12 test_map["./tests/while_loop.c"]=10 test_map["./tests/for_loop.c"]=6 test_map["./tests/function_call.c"]=17 test_map["./tests/recursive.c"]=24 test_map["./tests/bitwise.c"]=58 test_map["./tests/pointers.c"]=184 test_map["./tests/arrays.c"]=150 test_map["./tests/strings.c"]=5 test_map["./tests/edge_cases.c"]=12 # Error tests (expected to fail with non-zero exit code) declare -A error_test_map error_test_map["./tests/error_syntax.c"]="syntax" error_test_map["./tests/error_undefined_var.c"]="undefined" error_test_map["./tests/error_type_mismatch.c"]="type" # Test categories declare -A test_categories test_categories["./tests/add2.c"]="Basic" test_categories["./tests/arithmetic.c"]="Arithmetic" test_categories["./tests/comparison.c"]="Comparison" test_categories["./tests/logical.c"]="Logical" test_categories["./tests/if_else.c"]="Control Flow" test_categories["./tests/while_loop.c"]="Control Flow" test_categories["./tests/for_loop.c"]="Control Flow" test_categories["./tests/function_call.c"]="Functions" test_categories["./tests/recursive.c"]="Functions" test_categories["./tests/bitwise.c"]="Bitwise" test_categories["./tests/pointers.c"]="Pointers" test_categories["./tests/arrays.c"]="Arrays" test_categories["./tests/strings.c"]="Strings" test_categories["./tests/edge_cases.c"]="Edge Cases" test_categories["./tests/error_syntax.c"]="Error Tests" test_categories["./tests/error_undefined_var.c"]="Error Tests" test_categories["./tests/error_type_mismatch.c"]="Error Tests" print_header() { echo -e "${CYAN}╔══════════════════════════════════════════════════════════════════════════════╗${NC}" echo -e "${CYAN}║${WHITE} CCDJIT Comprehensive Test Suite ${CYAN}║${NC}" echo -e "${CYAN}╚══════════════════════════════════════════════════════════════════════════════╝${NC}" echo } print_test_header() { local test_file="$1" local category="${test_categories[$test_file]}" local test_name=$(basename "$test_file" .c) echo -e "${BLUE}┌─ ${WHITE}$test_name${BLUE} (${YELLOW}$category${BLUE})${NC}" echo -e "${BLUE}│${NC} File: $test_file" if [ -n "${test_map[$test_file]}" ]; then echo -e "${BLUE}│${NC} Expected: ${test_map[$test_file]}" elif [ -n "${error_test_map[$test_file]}" ]; then echo -e "${BLUE}│${NC} Expected: ${RED}ERROR${NC} (${error_test_map[$test_file]})" fi } print_test_result() { local test_file="$1" local expected="$2" local actual="$3" local status="$4" local is_error="$5" if [ "$status" == "PASS" ]; then if [ "$is_error" == "true" ]; then echo -e "${BLUE}│${NC} Result: ${GREEN}✓ PASSED${NC} (correctly failed with exit code $actual)" else echo -e "${BLUE}│${NC} Result: ${GREEN}✓ PASSED${NC} (got $actual)" fi echo -e "${BLUE}└─${GREEN} SUCCESS${NC}" else if [ "$is_error" == "true" ]; then echo -e "${BLUE}│${NC} Result: ${RED}✗ FAILED${NC} (expected error, got exit code $actual)" else echo -e "${BLUE}│${NC} Result: ${RED}✗ FAILED${NC} (expected $expected, got $actual)" fi echo -e "${BLUE}└─${RED} FAILURE${NC}" fi echo } print_summary() { local passed="$1" local failed="$2" local total="$3" local error_passed="$4" local error_failed="$5" local error_total="$6" echo -e "${CYAN}╔══════════════════════════════════════════════════════════════════════════════╗${NC}" echo -e "${CYAN}║${WHITE} Test Summary ${CYAN}║${NC}" echo -e "${CYAN}╠══════════════════════════════════════════════════════════════════════════════╣${NC}" if [ "$failed" -eq 0 ] && [ "$error_failed" -eq 0 ]; then echo -e "${CYAN}║${GREEN} All tests passed! ${WHITE}(${passed}/${total} functional, ${error_passed}/${error_total} error)${CYAN} ║${NC}" else echo -e "${CYAN}║${GREEN} Functional Tests: ${passed}/${total}${CYAN} │ ${RED}Failed: ${failed}${CYAN} ║${NC}" echo -e "${CYAN}║${GREEN} Error Tests: ${error_passed}/${error_total}${CYAN} │ ${RED}Failed: ${error_failed}${CYAN} ║${NC}" fi echo -e "${CYAN}╚══════════════════════════════════════════════════════════════════════════════╝${NC}" } run_functional_tests() { local count=0 local passed=0 local failed=0 echo -e "${PURPLE}Running Functional Tests...${NC}" >&2 echo >&2 for key in "${!test_map[@]}"; do print_test_header "$key" >&2 local output local exit_code local actual_result output=$(./bin/ccdjit "$key" 2>&1) exit_code=$? # Extract the actual result from "JIT returned: X" line actual_result=$(echo "$output" | grep "JIT returned:" | sed 's/.*JIT returned: //' | tail -1) if [ -z "$actual_result" ]; then actual_result=$exit_code fi if [ "${test_map[$key]}" = "$actual_result" ]; then print_test_result "$key" "${test_map[$key]}" "$actual_result" "PASS" "false" >&2 passed=$((passed+1)) else print_test_result "$key" "${test_map[$key]}" "$actual_result" "FAIL" "false" >&2 failed=$((failed+1)) fi count=$((count+1)) done echo "$passed $failed $count" } run_error_tests() { local count=0 local passed=0 local failed=0 echo -e "${PURPLE}Running Error Tests...${NC}" >&2 echo >&2 for key in "${!error_test_map[@]}"; do print_test_header "$key" >&2 local output local exit_code output=$(./bin/ccdjit "$key" 2>&1) exit_code=$? if [ $exit_code -ne 0 ]; then print_test_result "$key" "ERROR" "$exit_code" "PASS" "true" >&2 passed=$((passed+1)) else print_test_result "$key" "ERROR" "$exit_code" "FAIL" "true" >&2 failed=$((failed+1)) fi count=$((count+1)) done echo "$passed $failed $count" } run_all_tests() { print_header local func_results local error_results func_results=($(run_functional_tests)) error_results=($(run_error_tests)) # Ensure all stderr output is flushed before showing summary sleep 0.1 local func_passed=${func_results[0]} local func_failed=${func_results[1]} local func_total=${func_results[2]} local error_passed=${error_results[0]} local error_failed=${error_results[1]} local error_total=${error_results[2]} print_summary $func_passed $func_failed $func_total $error_passed $error_failed $error_total } run_single_test() { local test_file="$1" if [ -z "${test_map[$test_file]}" ] && [ -z "${error_test_map[$test_file]}" ]; then echo -e "${RED}Error: Test file '$test_file' not found in test suite${NC}" exit 1 fi print_header print_test_header "$test_file" local output local exit_code local actual_result output=$(./bin/ccdjit "$test_file" 2>&1) exit_code=$? # Extract the actual result from "JIT returned: X" line actual_result=$(echo "$output" | grep "JIT returned:" | sed 's/.*JIT returned: //' | tail -1) if [ -z "$actual_result" ]; then actual_result=$exit_code fi if [ -n "${test_map[$test_file]}" ]; then # Functional test if [ "${test_map[$test_file]}" = "$actual_result" ]; then print_test_result "$test_file" "${test_map[$test_file]}" "$actual_result" "PASS" "false" else print_test_result "$test_file" "${test_map[$test_file]}" "$actual_result" "FAIL" "false" fi else # Error test if [ $exit_code -ne 0 ]; then print_test_result "$test_file" "ERROR" "$exit_code" "PASS" "true" else print_test_result "$test_file" "ERROR" "$exit_code" "FAIL" "true" fi fi } list_tests() { echo -e "${CYAN}Available Tests:${NC}" echo echo -e "${GREEN}Functional Tests:${NC}" for key in "${!test_map[@]}"; do local category="${test_categories[$key]}" local test_name=$(basename "$key" .c) echo -e " ${WHITE}$test_name${NC} (${YELLOW}$category${NC}) - Expected: ${test_map[$key]}" done echo echo -e "${RED}Error Tests:${NC}" for key in "${!error_test_map[@]}"; do local category="${test_categories[$key]}" local test_name=$(basename "$key" .c) echo -e " ${WHITE}$test_name${NC} (${YELLOW}$category${NC}) - Expected: ERROR" done } show_help() { echo -e "${CYAN}CCDJIT Test Runner${NC}" echo echo "Usage: $0 [COMMAND] [OPTIONS]" echo echo "Commands:" echo " all Run all tests (functional + error)" echo " functional Run only functional tests" echo " error Run only error tests" echo " test Run a specific test file" echo " list List all available tests" echo " help Show this help message" echo echo "Examples:" echo " $0 all" echo " $0 functional" echo " $0 test ./tests/arithmetic.c" echo " $0 list" } # Main script logic case "$1" in "all") run_all_tests ;; "functional") print_header func_results=($(run_functional_tests)) sleep 0.1 print_summary ${func_results[0]} ${func_results[1]} ${func_results[2]} 0 0 0 ;; "error") print_header error_results=($(run_error_tests)) sleep 0.1 print_summary 0 0 0 ${error_results[0]} ${error_results[1]} ${error_results[2]} ;; "test") if [ -z "$2" ]; then echo -e "${RED}Error: Please specify a test file${NC}" exit 1 fi run_single_test "$2" ;; "list") list_tests ;; "help"|"-h"|"--help") show_help ;; "") show_help ;; *) echo -e "${RED}Error: Unknown command '$1'${NC}" echo "Use '$0 help' for usage information" exit 1 ;; esac