#!/usr/bin/env bash # # Use (to override results) # # NDPI_FORCE_UPDATING_UTESTS_RESULTS=1 ./do.sh # # To run tests in parallel: (you need **GNU** `parallel` program) # # NDPI_FORCE_PARALLEL_UTESTS=1 ./do.sh cd "$(dirname "${0}")" || exit 1 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 FORCE_PARALLEL_UTESTS=0 if [ "${NDPI_FORCE_PARALLEL_UTESTS}" = "1" ]; then FORCE_PARALLEL_UTESTS=1 fi SKIP_PARALLEL_BAR=0 if [ "${NDPI_SKIP_PARALLEL_BAR}" = "1" ]; then SKIP_PARALLEL_BAR=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@ PCRE2_ENABLED=@PCRE2_ENABLED@ PCRE_PCAPS="WebattackRCE.pcap" NBPF_ENABLED=@NBPF_ENABLED@ NBPF_PCAPS="h323-overflow.pcap" GLOBAL_CONTEXT_ENABLED=@GLOBAL_CONTEXT_ENABLED@ GLOBAL_CONTEXT_CFGS="caches_global" READER="${CMD_PREFIX} ../../../example/ndpiReader${EXE_SUFFIX} --cfg=filename.config,../../../example/config.txt -A -p ../../../example/protos.txt -c ../../../example/categories.txt -r ../../../example/risky_domains.txt -j ../../../example/ja3_fingerprints.csv -S ../../../example/sha1_fingerprints.csv -G ../../../lists -q -K JSON -k /dev/null -t -v 2" #These exports are used in parallel mode export CMD_DIFF export CMD_WDIFF export CMD_COLORDIFF export PCRE2_ENABLED export PCRE_PCAPS export NBPF_ENABLED export NBPF_PCAPS export READER export FORCE_UPDATING_UTESTS_RESULTS export FORCE_PARALLEL_UTESTS 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 #For parallel tests you need `parallel` from GNU, not from `moreutils` package! #On Ubuntu, for example, you might need to explicitly run `apt install parallel` if [ $FORCE_PARALLEL_UTESTS -eq 1 ]; then if ! parallel -V | grep -qoE 'GNU parallel'; then echo "$0: To run the test in parallel mode you need **GNU** 'parallel'" echo "$0: Try something like 'apt install parallel'" exit 1 fi 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 } run_single_pcap() { f=$1 if [ ! -f "./pcap/$f" ]; then return 0 fi SKIP_PCAP=0; if [ $PCRE2_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 if [ $FORCE_PARALLEL_UTESTS -eq 1 ]; then printf "SKIPPED\n" else printf "%-48s\tSKIPPED\n" "$f" fi return 0 fi 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 ] && [ -f /tmp/reader.$$.out ]; then # create result files if not present if [ ! -f "result/$f.out" ]; then cp /tmp/reader.$$.out "result/$f.out" fi NUM_DIFF=$(${CMD_DIFF} "result/$f.out" /tmp/reader.$$.out | wc -l) else if [ $FORCE_PARALLEL_UTESTS -eq 1 ]; then printf "ERROR (ndpiReader${EXE_SUFFIX} exit code: ${CMD_RET})\n" else printf "%-48s\tERROR (ndpiReader${EXE_SUFFIX} exit code: ${CMD_RET})\n" "$f" FAILURES+=("$f") #TODO: find a way to update this variable also in parallel mode fi return 1 fi if [ "$NUM_DIFF" -eq 0 ]; then if [ $FORCE_PARALLEL_UTESTS -eq 0 ]; then printf "%-48s\tOK\n" "$f" fi return 0 else if [ $FORCE_PARALLEL_UTESTS -eq 1 ]; then printf "ERROR\n" else printf "%-48s\tERROR\n" "$f" FAILURES+=("$f") #TODO: find a way to update this variable also in parallel mode fi echo "$CMD [old vs new]" ${CMD_DIFF} "result/$f.out" /tmp/reader.$$.out if [ ! -z "${CMD_COLORDIFF}" ] && [ ! -z "${CMD_WDIFF}" ]; then ${CMD_WDIFF} -n -3 "result/$f.out" /tmp/reader.$$.out | sort | uniq | ${CMD_COLORDIFF} fi if [ $FORCE_UPDATING_UTESTS_RESULTS -eq 1 ]; then cp /tmp/reader.$$.out "result/$f.out" fi fi /bin/rm -f /tmp/reader.$$.out return 1 } export -f run_single_pcap check_results() { if [ $FORCE_PARALLEL_UTESTS -eq 1 ]; then if [ $SKIP_PARALLEL_BAR -eq 1 ]; then parallel --tag "run_single_pcap" ::: $PCAPS else parallel --bar --tag "run_single_pcap" ::: $PCAPS fi RET=$? #Number of failed job up to 100 RC=$(( RC + RET )) else for f in $PCAPS; do run_single_pcap "$f" RET=$? RC=$(( RC + RET )) done fi 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 SKIP_CFG=0 if [ $GLOBAL_CONTEXT_ENABLED -eq 0 ]; then for c in $GLOBAL_CONTEXT_CFGS; do if [ "$c" = "$(basename "$d")" ]; then SKIP_CFG=1 break fi done fi if [ $SKIP_CFG -eq 1 ]; then printf "Configuration \"$(basename "$d")\" %-18s\tSKIPPED\n" continue fi cd ./cfgs/"$(basename "$d")" || exit 1 if [ "$#" -ne 0 ]; then PCAPS=$* else PCAPS=$(cd pcap || exit 1; /bin/ls -- *.*cap*) fi FAILURES=() READER_EXTRA_PARAM="" [ -f config.txt ] && READER_EXTRA_PARAM=$(< config.txt) export READER_EXTRA_PARAM echo "Run configuration \"$(basename "$d")\" [$READER_EXTRA_PARAM]" check_results test ${#FAILURES} -ne 0 && printf '%s: %s\n' "${0}" "${RC} pcap(s) failed" test ${#FAILURES} -ne 0 && echo "Failed: " "${FAILURES[@]}" cd ../../ done exit $RC