#!/bin/bash
set +x

source ../../common.tst

# use geninfo to capture - so we collect coverage data...
CAPTURE="$GENINFO_TOOL ."
# CAPTURE="$LCOV_TOOL --capture -d ."


LCOV_OPTS="--branch-coverage $PARALLEL $PROFILE"

IFS='.' read -r -a VER <<< `${CC} -dumpversion`

rm -rf *.gcda *.gcno a.out *.info* *.txt* *.json dumper* testRC *.gcov *.gcov.* *.log precedence.rc

clean_cover

if [[ 1 == $CLEAN_ONLY ]] ; then
    exit 0
fi

if ! type ${CXX} >/dev/null 2>&1 ; then
        echo "Missing tool: ${CXX}" >&2
        exit 2
fi

${CXX} -std=c++1y --coverage exception.cpp
if [ 0 != $? ] ; then
    echo "Error:  unexpected error from gcc"
    exit 1
fi
NO_INITIAL_CAPTURE=0
if [[ "${VER[0]}" -gt 4 && "${VER[0]}" -lt 7 ]] ; then
    # no data generated by initial capture
    IGNORE_EMPTY="--ignore empty"
    NO_INITIAL_CAPTURE=1
fi
if [ "${VER[0]}" -lt 8 ] ; then
    # cannot generate branch data unless 'intermediate'
    IGNORE_USAGE="--ignore usage"
fi
$COVER $CAPTURE $LCOV_OPTS --initial -o initial.info $IGNORE_EMPTY $IGNORE_USAGE
if [ $NO_INITIAL_CAPTURE != $? ] ; then
    echo "Error:  unexpected error code from lcov --initial"
    if [ $KEEP_GOING == 0 ] ; then
        exit 1
    fi
fi

# enable branch filter without line/region filter - to hit some additional code
$COVER $CAPTURE $LCOV_OPTS --initial -o initial_br.info $IGNORE_EMPTY $IGNORE_USAGE --filter branch_region
if [ $NO_INITIAL_CAPTURE != $? ] ; then
    echo "Error:  unexpected error code from lcov --initial"
    if [ $KEEP_GOING == 0 ] ; then
        exit 1
    fi
fi
for info in initial.info initial_br.info ; do
    grep 'BRDA:8,e0' $info
    if [ 0 == $? ] ; then
	echo "Error:  exception branch should be filtered out of $info"
	if [ $KEEP_GOING == 0 ] ; then
            exit 1
	fi
    fi
done

./a.out
if [ 0 != $? ] ; then
    echo "Error:  unexpected error return from a.out"
    exit 1
fi

$COVER $CAPTURE $LCOV_OPTS -o all.info --include '*/exception.cpp' --no-markers

if [ 0 != $? ] ; then
    echo "Error:  unexpected error code from lcov extract"
    if [ $KEEP_GOING == 0 ] ; then
        exit 1
    fi
fi

$COVER $LCOV_TOOL $LCOV_OPTS --list all.info

if [ 0 != $? ] ; then
    echo "Error:  unexpected error code from lcov --list"
    if [ $KEEP_GOING == 0 ] ; then
        exit 1
    fi
fi

# how many branches reported?
BRANCHES=`grep -c BRDA: all.info`
EXCEPTIONS=`grep -c ',e' all.info`

if [ $EXCEPTIONS != '0' ] ; then

    # when run without 'no markers", then we should remove exception
    #  branches in the marked region
    $COVER $CAPTURE $LCOV_OPTS -o filter.info --include '*/exception.cpp' | tee noFilter.log
    if [ 0 != ${PIPESTATUS[0]} ] ; then
        echo "Error:  unexpected error code from lcov extract filter"
        if [ $KEEP_GOING == 0 ] ; then
            exit 1
        fi
    fi
    FILTER_BRANCHES=`grep BRDA: filter.info | grep -v U | wc -l`
    FILTER_EXCEPTIONS=`grep BRDA: filter.info | grep -v U | grep -c ',e'`
    [[ `grep BRF filter.info` =~ ([0-9]+)$ ]]
    FOUND=${BASH_REMATCH[1]}
    [[ `grep BRH filter.info` =~ ([0-9]+)$ ]]
    HIT=${BASH_REMATCH[1]}
    if [ $FILTER_BRANCHES != "$FOUND" ] ; then
	echo "Error: wrong branch count after exception filter"
	exit 1;
    fi

    # we expect the number of exception branches found in 'filter.info'
    #  (when we applied 'exception branch markers') should be the less than
    # the number of total branches (when we excluded nothing)
    if [ $FILTER_BRANCHES -ge $BRANCHES ] ; then
        echo "Error:  did not filter exception branches: $BRANCHES -> $FILTER_BRANCHES"
        exit 1
    fi
    let DIFF=$BRANCHES-$FILTER_BRANCHES
    let DIFF2=$EXCEPTIONS-$FILTER_EXCEPTIONS
    # 'DIFF' is the number of branches that got removed by 'marker' filtering
    #   we expect that to be the same as the number of exception branches that
    #   got removed
    # however, this is slightly complicated because gcc might not have
    #   all the exception branches - leaving a long "exception not taken"
    #   branch on the line...but we explicitly remove such lone
    #   branches - so the total difference in number of branches might
    #   larger than the difference between the 'e' branches in the info files.
    if [ $DIFF -lt $DIFF2 ] ; then
        echo "Error: we seem to have filtered non-exception branches: $DIFF -> $DIFF2"
        exit 1
    fi

    # override the exclusion markers and check that we didn't remove
    #  exception branches..
    $COVER $CAPTURE $LCOV_OPTS -o override.info --include '*/exception.cpp' --rc lcov_excl_exception_br_start=nomatch_start --rc lcov_excl_exception_br_stop=nomatch_stop --rc lcov_excl_exception_br_line=notThere

    if [ 0 != $? ] ; then
        echo "Error:  unexpected error code from lcov exclusion override filter"
        if [ $KEEP_GOING == 0 ] ; then
            exit 1
        fi
    fi
    FILTER_BRANCHES=`grep BRDA: override.info | grep -v U | wc -l`
    if [ $FILTER_BRANCHES != $BRANCHES ] ; then
        echo "did not honor exception overrides.  Expected $BRANCHES found $FILTER_BRANCHES"
        if [ $KEEP_GOING == 0 ] ; then
            exit 1
        fi
    fi

else
    echo "no exceptions identified - so nothing to do"
fi

# test some filtering options
$COVER $CAPTURE $LCOV_OPTS -o vanilla.info --ignore inconsistent
if [ 0 != $? ] ; then
    echo "Error:  unexpected error code from vanilla capture-external"
    if [ $KEEP_GOING == 0 ] ; then
        exit 1
    fi
fi
VANILLA_LINES=`grep -c '^DA:' vanilla.info`
VANILLA_FILES=`grep -c 'SF:' vanilla.info`

$COVER $CAPTURE $LCOV_OPTS -o no_external.info --no-external
if [ 0 != $? ] ; then
    echo "Error:  unexpected error code from capture no-external"
    if [ $KEEP_GOING == 0 ] ; then
        exit 1
    fi
fi
NO_EXTERNAL_LINES=`grep -c '^DA:' no_external.info`

if [ $VANILLA_FILES == 1 ]  ; then
    if ["$NO_EXTERNAL_LINES" != "$VANILLA_LINES" ] ; then
	echo "Error: unexpected line count when there are no external files (gcc/5.2.0, say)"
	if [ $KEEP_GOING == 0 ] ; then
            exit 1
	fi
    fi
else
    if [ "$NO_EXTERNAL_LINES" -ge "$VANILLA_LINES" ] ; then
	echo "Error: no_external had no effect $NO_EXTERNAL_LINES -> $VANILLA_LINES"
	if [ $KEEP_GOING == 0 ] ; then
            exit 1
	fi
    fi
fi

$COVER $CAPTURE $LCOV_OPTS -o external_0.info --rc geninfo_external=0
if [ 0 != $? ] ; then
    echo "Error:  unexpected error code from geninfo_external=0"
    if [ $KEEP_GOING == 0 ] ; then
        exit 1
    fi
fi
diff no_external.info external_0.info
if [ $? != 0 ] ; then
    echo "geninfo_external=0 didn't work"
    if [ $KEEP_GOING == 0 ] ; then
        exit 1
    fi
fi

EXTERNAL_0_LINES=`grep -c '^DA:' external_0.info`
echo "geninfo_external = 0" > precedence.rc
$COVER $CAPTURE $LCOV_OPTS -o external_1.info --rc geninfo_external=1 --config-file precedence.rc --ignore inconsistent
if [ 0 != $? ] ; then
    echo "Error:  unexpected error code from geninfo_external=1"
    if [ $KEEP_GOING == 0 ] ; then
        exit 1
    fi
fi
diff vanilla.info external_1.info
if [ $? != 0 ] ; then
    echo "geninfo_external=1 didn't work"
    if [ $KEEP_GOING == 0 ] ; then
        exit 1
    fi
fi


$COVER $LCOV_TOOL $LCOV_OPTS -o filtExceptOrphan.info -a example.data --filter exception,orphan 2>&1 | tee exceptOrphanFilter.log
if [ 0 != ${PIPESTATUS[0]} ] ; then
    echo "Error:  unexpected error code from except/orphan filtering"
    if [ $KEEP_GOING == 0 ] ; then
        exit 1
    fi
fi
BRANCH_RPT=`grep branches... exceptOrphanFilter.log`
$COVER $LCOV_TOOL $LCOV_OPTS --summary filtExceptOrphan.info | tee summaryFilt.log
SUMMARY_RPT=`grep branches... summaryFilt.log`
if [ "$BRANCH_RPT" != "$SUMMARY_RPT" ] ; then
    echo "Error:  extract '$BRANCH_RPT' and summary '$SUMMARY_RPT' reports are different"
    if [ $KEEP_GOING == 0 ] ; then
        exit 1
    fi
fi


$COVER $LCOV_TOOL $LCOV_OPTS -o filtExcept.info -a example.data --filter exception 2>&1 | tee exceptFilter.log
if [ 0 != ${PIPESTATUS[0]} ] ; then
    echo "Error:  unexpected error code from except filering"
    if [ $KEEP_GOING == 0 ] ; then
        exit 1
    fi
fi
$COVER $LCOV_TOOL $LCOV_OPTS -o filtOrphan.info -a example.data --filter orphan 2>&1 | tee orphanFilter.log
if [ 0 != ${PIPESTATUS[0]} ] ; then
    echo "Error:  unexpected error code from orphan filering"
    if [ $KEEP_GOING == 0 ] ; then
        exit 1
    fi
fi
N=`grep -c BRDA: example.data`
E=`grep -c BRDA: filtExcept.info`
O=`grep -c BRDA: filtOrphan.info`
EO=`grep -c BRDA: filtExceptOrphan.info`

# strict ordering
if [ "$N" -le "$EO" ] ; then
    echo "exception/orphan count"
    if [ $KEEP_GOING == 0 ] ; then
        exit 1
    fi
fi
if [ "$E" -le "$EO" ] || [ "$E" -ge "$N" ] ; then
    echo "exception $E <-> exception/orphan $EO N $N count"
    if [ $KEEP_GOING == 0 ] ; then
        exit 1
    fi
fi
if [ "$O" -le "$EO" ] || [ "$O" -ge "$N" ] ; then
    echo "N: $N exception $E orphan $O  <-> exception/orphan $EO count"
    if [ $KEEP_GOING == 0 ] ; then
        exit 1
    fi
fi

echo "Tests passed"

if [ "x$COVER" != "x" ] && [ $LOCAL_COVERAGE == 1 ]; then
    cover
fi
