#!/bin/bash

cd "$(dirname "${0}")"

FUZZY_TESTING_ENABLED=@BUILD_FUZZTARGETS@
if [ "${NDPI_DISABLE_FUZZY}" = "1" ]; then
   FUZZY_TESTING_ENABLED=0
fi

FORCE_UPDATING_UTESTS_RESULTS=0
if [ "${NDPI_FORCE_UPDATING_UTESTS_RESULTS}" = "1" ]; then
   FORCE_UPDATING_UTESTS_RESULTS=1
fi

#Remember: valgrind and *SAN are incompatible!
CMD_PREFIX="${CMD_PREFIX}"
if [ "${NDPI_TESTS_WINE}" = "1" ]; then
   CMD_PREFIX="wine"
elif [ "${NDPI_TESTS_VALGRIND}" = "1" ]; then
   CMD_PREFIX="valgrind -q --leak-check=full"
fi

CMD_DIFF="$(which diff)"
CMD_WDIFF="$(which wdiff)"
CMD_COLORDIFF="$(which colordiff)"

EXE_SUFFIX=@EXE_SUFFIX@
GPROF_ENABLED=@GPROF_ENABLED@
PCRE_ENABLED=@PCRE_ENABLED@
PCRE_PCAPS="WebattackRCE.pcap"
NBPF_ENABLED=@NBPF_ENABLED@
NBPF_PCAPS="h323-overflow.pcap"
READER="${CMD_PREFIX} ../../../example/ndpiReader${EXE_SUFFIX} -A -p ../../../example/protos.txt -c ../../../example/categories.txt -r ../../../example/risky_domains.txt -j ../../../example/ja3_fingerprints.csv -S ../../../example/sha1_fingerprints.csv -q -K JSON -k /dev/null -t -v 2"

RC=0

if [ ! -x "../example/ndpiReader${EXE_SUFFIX}" ]; then
  echo "$0: Missing ../example/ndpiReader${EXE_SUFFIX}"
  echo "$0: Run ./configure and make first"
  exit 1
fi

if [ ${GPROF_ENABLED} -eq 1 ]; then
  GPROF="${GPROF:-$(which pprof)}"
  if [ ! -x "${GPROF}" ]; then
    echo "$0: ${GPROF} not found or not executable"
    exit 1
  fi
  echo "$0: Using pprof executable ${GPROF}"
  echo "$0: Please make sure that you use google-pprof and not gperftools"
  echo "$0: See https://github.com/google/pprof"
else
  GPROF=false
fi

fuzzy_testing() {
    if [ -f ../fuzz/fuzz_ndpi_reader ]; then
	cp ../example/protos.txt .
	cp ../example/categories.txt .
	cp ../example/risky_domains.txt .
	cp ../example/ja3_fingerprints.csv .
	cp ../example/sha1_fingerprints.csv .
	../fuzz/fuzz_ndpi_reader -dict=../fuzz/dictionary.dict -max_total_time="${MAX_TOTAL_TIME:-592}" -print_pcs=1 -workers="${FUZZY_WORKERS:-0}" -jobs="${FUZZY_JOBS:-0}" cfgs/default/pcap/
	rm -f protos.txt categories.txt risky_domains.txt ja3_fingerprints.csv sha1_fingerprints.csv
    fi
}

build_results() {
    for f in $PCAPS; do
	#echo $f
	# create result files if not present
	if [ ! -f result/$f.out ]; then
	    CMD="$READER -i pcap/$f -w result/$f.out $READER_EXTRA_PARAM"
	    $CMD
	fi
    done
}

check_results() {
	for f in $PCAPS; do
	    if [ -n "$*" ]; then
	    	SKIP_PCAP=1
		for i in $* ; do [ "$f" = "$i" ] && SKIP_PCAP=0 && break ; done
		[ $SKIP_PCAP = 1 ] && continue
	    fi
	    SKIP_PCAP=0
	    if [ $PCRE_ENABLED -eq 0 ]; then
	      for p in $PCRE_PCAPS; do
	        if [ $f = $p ]; then
	          SKIP_PCAP=1
	          break
	        fi
	      done
	    fi
	    if [ $NBPF_ENABLED -eq 0 ]; then
	      for p in $NBPF_PCAPS; do
	        if [ $f = $p ]; then
	          SKIP_PCAP=1
	          break
	        fi
	      done
	    fi
	    if [ $SKIP_PCAP -eq 1 ]; then
	        printf "%-32s\tSKIPPED\n" "$f"
	        continue
	    fi

	if [ -f result/$f.out ]; then
	    CMD="$READER -i pcap/$f -w /tmp/reader.$$.out $READER_EXTRA_PARAM"
	    CPUPROFILE=./result/$f.cprof HEAPPROFILE=./result/$f $CMD
	    CMD_RET=$?
	    if [ $CMD_RET -eq 0 ]; then
	      NUM_DIFF=`${CMD_DIFF} result/$f.out /tmp/reader.$$.out | wc -l`
	    else
	      printf "%-48s\tERROR (ndpiReader${EXE_SUFFIX} exit code: ${CMD_RET})\n" "$f"
	      RC=$(( RC + 1 ))
	      FAILURES+=("$f.out")
	      continue
	    fi

		if [ $NUM_DIFF -eq 0 ]; then
		  printf "%-48s\tOK\n" "$f"
		else
		  printf "%-48s\tERROR\n" "$f"
		  echo "$CMD [old vs new]"
		  ${CMD_DIFF} result/$f.out /tmp/reader.$$.out
		  if [ ! -z "${CMD_COLORDIFF}" -a ! -z "${CMD_WDIFF}" ]; then
		    ${CMD_WDIFF} -n -3 result/$f.out /tmp/reader.$$.out | sort | uniq | ${CMD_COLORDIFF}
		  fi
		  RC=$(( RC + 1 ))
		  FAILURES+=("$f.out")
		  if [ $FORCE_UPDATING_UTESTS_RESULTS -eq 1 ]; then
		    cp /tmp/reader.$$.out result/$f.out
		  fi
	    fi

	    /bin/rm -f /tmp/reader.$$.out
	fi
    done

    if [ ${GPROF_ENABLED} -eq 1 ]; then
      GPROF_ARGS='-nodecount 100 -nodefraction 0 -symbolize=fastlocal'
      ${GPROF} -top ${GPROF_ARGS} ../../../example/ndpiReader${EXE_SUFFIX} ./result/*.cprof || exit 1
      ${GPROF} -png -output ./result/cpu_profile.png ${GPROF_ARGS} ../../../example/ndpiReader${EXE_SUFFIX} ./result/*.cprof || exit 1
      ${GPROF} -top ${GPROF_ARGS} -sample_index=alloc_space  ../../../example/ndpiReader${EXE_SUFFIX} ./result/*.heap || exit 1
      ${GPROF} -png -output ./result/heap_profile.png ${GPROF_ARGS} -sample_index=alloc_space ../../../example/ndpiReader${EXE_SUFFIX} ./result/*.heap || exit 1
    fi
}

if [ $FUZZY_TESTING_ENABLED -eq 1 ]; then
    fuzzy_testing
fi

for d in $(find ./cfgs/* -type d -maxdepth 0 2>/dev/null) ; do
    cd ./cfgs/"$(basename $d)"

    PCAPS=`cd pcap; /bin/ls *.*cap*`
    FAILURES=()
    READER_EXTRA_PARAM=""
    [ -f config.txt ] && READER_EXTRA_PARAM=$(< config.txt)

    echo "Run configuration \""$(basename $d)"\" [$READER_EXTRA_PARAM]"

    build_results
    check_results $*

    test ${RC} -ne 0 && printf '%s: %s\n' "${0}" "${RC} pcap(s) failed"
    test ${RC} -ne 0 && echo "Failed: ${FAILURES[@]}"

    cd ../../
done

exit $RC