# You can adjust the build output and behavior with these symbols

#VERBOSE=vtest      #Uncomment to announce each test

#GCOV="Y"           #Uncomment to check test coverage

MONITORED_BUILD="Y" #Comment out to turn off coverage and printf monitoring


#-------------------------------------------------
# You should not change below this line

export CPPUTEST_HOME=/cpputest
export GCOV_ARGS+="-b -c"
CAPTURED_GCOV_RUN=gcov.out
MONITORED_BUILD_SPEC=monitored-build.txt

build()
{
    if [ "$GCOV" == "Y" ]; then
        make_gcov
    elif [ "$MONITORED_BUILD" == "Y" ]; then
        MONITORED_FILE=$(cat $MONITORED_BUILD_SPEC)
        monitored_build
    else
        make $VERBOSE
    fi
}

make_gcov()
{
    make CPPUTEST_USE_GCOV=Y gcov
    status=$?
    find . -name "*.*.gcov" | xargs cat
}

monitored_build()
{
    make CPPUTEST_USE_GCOV=Y gcov $VERBOSE >$CAPTURED_GCOV_RUN
    makeup_for_gcov_not_returing_status
    status=$?
    get_rid_of_gcov_noise
    print_untested_code
    print_lines_with_printf
    return $status
}

mark_test_run_yellow()
{
    sed -i -e's/^OK /OK, But so what! /' $CAPTURED_GCOV_RUN
}

dashed_line()
{
    echo "--------------------------------------------------------------"
}

print_coverage()
{
    dashed_line
    find . -name "${MONITORED_FILE}.gcov" | xargs cat
    dashed_line
}

get_rid_of_gcov_noise()
{
    egrep -v "filterGcov|^[ 1][ 0-9][0-9]?\.[0-9][0-9]%|See gcov directory|Creating .*\.gcov"  $CAPTURED_GCOV_RUN
}

find_printfs()
{
    grep --line-number printf ${MONITORED_FILE}
}

untested_lines()
{
    find . -name "${MONITORED_FILE}.gcov" | xargs grep "#####: "
}

dead_branches()
{
    find . -name "${MONITORED_FILE}.gcov" | xargs grep "taken 0"
}

makeup_for_gcov_not_returing_status()
{
    if [ "$(grep -c 'OK '  $CAPTURED_GCOV_RUN)" = "1" ]; then
        return 0
    else
        return 3
    fi
}

print_untested_code()
{
    [[ "$(untested_lines)" != "" ]] && lines="Y" || lines="N"
    [[ "$(dead_branches)" != "" ]] && branches="Y" || branches="N"

    if [ ${status} -eq 0 ]; then
        if [ "${lines}" == "Y" ] || [ "${branches}" == "Y" ]; then
            print_untested_code_message $lines $branches
            print_coverage
            mark_test_run_yellow
            status=$((status+42))
        fi
    fi
}

print_untested_code_message()
{
    lines=$1
    branches=$2
    both="${lines}${branches}"

    echo "It looks like YOUR CODE GOT AHEAD OF YOUR TESTS!"
    if [ "${both}" == "YY" ]; then
        echo "You have lines of code and branches not covered by your tests."
    fi
    print_untested_lines_message $lines
    print_dead_branches_message $branches
}

print_untested_lines_message()
{
    if [ "$1" == "Y" ]; then
        echo
        echo "These lines are not covered by your tests:"
        untested_lines
        echo ""
            echo "Look for '#####:' in the coverage report below to see your"
            echo "untested code in context."
        echo
    fi
}

print_dead_branches_message()
{
    if [ "$1" == "Y" ]; then
        echo ""
        echo "Look for 'taken 0' in the coverage report below to find the"
        echo "branches not covered by your tests."
        echo
        echo "This page has a good explanation of branch coverage:"
        echo "    https://www.cs.odu.edu/~zeil/cs333/website-s12/Lectures/wbtesting/pages/gcov-branch.html"
        echo
    fi
}

print_lines_with_printf()
{
    printfs=$(find_printfs)
    if [ "${printfs}" != "" ]; then
        print_found_printf_message "${printfs}"
        dashed_line
        mark_test_run_yellow
        status=$((status+100))
    fi
}

print_found_printf_message()
{
    cat <<EOF

printf found on these lines:

$1

Do you really need printf now? Are you debugging?

Not that you'll never need printf to find a bug, but I'd like you to
work in small steps where you usually only have one thing wrong at a
time.

I suspect you wrote too much code. TDD uses small deliberate steps
to help avoid debugging.

Now, I suggest you revert you code to the last time it worked and
try again.  You probably won't make the same mistake.

To revert your code to any prior test run, click a previous traffic signal
(a green one preferably), then choose revert.  At any rate, you'll need to
get rid of printf to get back to green.

Maybe you can get some help from your instructor too.

EOF

}

core_dumped_fault_help()
{
    cat error.out <<EOF

Running tests again with verbose enabled."
The last test started may lead you to the error."

EOF
    make vtest
    echo
}

output_for_test_run()
{
    if [ "$(grep "(core dumped)" error.out | wc -l)" != "0" ]; then
        core_dumped_fault_help >seg.out 2>seg-error.out
        cat seg.out seg-error.out
    else
        cat test.out error.out
    fi
}

cleanup()
{
    rm -f *.out
    rm -f *_tests.txt
    rm -f $CAPTURED_GCOV_RUN
    rm -rf gcov
}

build >test.out 2>error.out
status=$?
output_for_test_run
cleanup

exit $status
