#!/bin/bash

# Path where the script needs to output the .tap result
FULL_LOGS_PATH="/var/log/redtest/audit-clangtidy-misra"
# Path to the 'MISRAPlugin.so' shared library
MISRA_PLUGIN_SO="/usr/lib/MISRAPlugin.so"
# Path to the directory containing the '*.c' files to run the tests
TEST_FILES_DIR="/usr/libexec/redtest/audit-clangtidy-misra"
# Path to the python script running the clang-tidy tests
CHECK_CLANG_TIDY_PATH="/usr/libexec/redtest/audit-clangtidy-misra/check_clang_tidy.py"

# TAP variables used
TAP_COUNTER=0
TAP_FILE_CONTENT=""

# Variable used to display results at the end
SUCCEEDED_TESTS=""
FAILED_TESTS=""
SKIPPED_TESTS=""

# Function to display script usage
usage() {   
    echo "Usage: $0 [OPTIONS]"
    echo "Options:"
    echo " -c, --check-script  Path to the python script running the clang-tidy tests"
    echo " -h, --help          Display this help message"
    echo " -l, --logs-dir      Directory to store the tests result"
    echo " -s, --so            Path to the shared library to test"
    echo " -t, --tests-dir     Path to the '.c' sample files used for test"
    echo ""
    echo "Example of command:"
    echo "    $0"
    echo "    $0 -l tap-logs/ -s build/lib/clang-tidy/MISRAPlugin.so -c test/check_clang_tidy.py -t test/"
}

# Function to handle options and arguments
handle_options() {
    while [ $# -gt 0 ]; do
        case $1 in
            -c | --check-script)
                CHECK_CLANG_TIDY_PATH="$2"
                shift
                ;;
            -h | --help)
                usage
                exit 0
                ;;
            -l | --logs-dir)
                FULL_LOGS_PATH="$2"
                shift
                ;;
            -s | --so)
                MISRA_PLUGIN_SO="$2"
                shift
                ;;
            -t | --tests-dir)
                TEST_FILES_DIR="$2"
                shift
                ;;
            *)
                echo "Invalid option: $1" >&2
                usage
                exit 1
                ;;
        esac
        shift
    done
}

# Function used to update the TAP file used as result
updatetap()
{
	# Get the given parameters
	test_def="$1"
	test_result="$2"
    test_directive="$3"

	# Increment counter
	let TAP_COUNTER++

    # Create line
    line="$test_result $TAP_COUNTER - $test_def $test_directive\n"

	# Add a new line to the file to write
	TAP_FILE_CONTENT="${TAP_FILE_CONTENT}${line}"
}

# Function used to write the TAP file
finalizetap()
{
	echo "1..$TAP_COUNTER" > $TAP_FILE
	printf "$TAP_FILE_CONTENT" >> $TAP_FILE
}

echo "####################################"
echo "#####    MISRA PLUGIN TESTS    #####"
echo "####################################"
echo ""

# Handle the potential flags given by the user (but we can work without any -> this is the redpesk factory use case)
handle_options "$@"

TAP_FILE="$FULL_LOGS_PATH/audit-clangtidy-misra.tap"

echo "Running with the following parameters:"
echo "    -> FULL_LOGS_PATH:        '$FULL_LOGS_PATH'"
echo "    -> MISRA_PLUGIN_SO:       '$MISRA_PLUGIN_SO'"
echo "    -> TEST_FILES_DIR:        '$TEST_FILES_DIR'"
echo "    -> CHECK_CLANG_TIDY_PATH: '$CHECK_CLANG_TIDY_PATH'"
echo ""

echo "Logs directory creation"
mkdir -p $FULL_LOGS_PATH
echo -e "    -> OK\n"

echo "Discovering available rules to test"
misra_rules_available=$(clang-tidy --checks=-*,misra-rule-* -load="$MISRA_PLUGIN_SO" --list-checks | grep "misra-rule-")

# Create an array from the return value
IFS=$'\n' read -r -d '' -a rules_array < <(printf '%s\0' "$misra_rules_available")

# Clean the spaces
for i in "${!rules_array[@]}"; do
  rules_array[$i]="${rules_array[$i]#"${rules_array[$i]%%[![:space:]]*}"}"
done
echo -e "    -> OK\n"

echo "Run the tests available"
for rule in "${rules_array[@]}"
do  
    echo ""
    echo ""
    echo "##### About to test rule: $rule"

    # From the rule, construct the sample filename
    stripped="${rule#misra-rule-}"
    filename="${stripped/-/_}.c"
    filename_output="output_$filename"

    # Check if there is a test available for this rule
    echo "Looking for file $filename"
    found_path=$(find "$TEST_FILES_DIR" -type f -name "$filename" -print -quit)
    if [[ -n $found_path ]]; then
        echo "    - File found: $found_path"
        
        echo "Running test with command: $CHECK_CLANG_TIDY_PATH $found_path $rule $filename_output -- -load=$MISRA_PLUGIN_SO"
        output=$($CHECK_CLANG_TIDY_PATH $found_path $rule $filename_output -- -load=$MISRA_PLUGIN_SO 2>&1)
        result=$?

        if [[ $result -eq 0 ]]
        then
            echo "    - TEST OK"
            
            # Remove the output files since everything went well
            rm "$filename_output.c"
            rm "$filename_output.c.msg"
            rm "$filename_output.orig"

            # Update the TAP file
            updatetap "$rule" "ok" ""

            # Update the result string
            SUCCEEDED_TESTS="$SUCCEEDED_TESTS $stripped,"

        else
            echo "    - TEST FAILED"
            echo "Output:"
            echo "$output"

            # Update the TAP file
            updatetap "$rule" "not ok" ""

            # Update the result string
            FAILED_TESTS="$FAILED_TESTS $stripped,"
        fi
    else
        echo "    - File not found for '$rule': SKIP TEST"
        
        # Update the TAP file
        updatetap "$rule" "ok" "# skip Test not implemented currently"

        # Update the result string
        SKIPPED_TESTS="$SKIPPED_TESTS $stripped,"
    fi
done

# End of the test, finalize the TAP file
finalizetap

# Display the results
echo ""
echo ""
echo "##### RESULTS #####"
echo "PASS:$SUCCEEDED_TESTS"
echo "FAIL:$FAILED_TESTS"
echo "SKIP:$SKIPPED_TESTS"
echo "###################"

exit 0