#!/usr/bin/env bash

PROGNAME="${BASH_SOURCE[0]}"
HERE="$(cd "$(dirname "$PROGNAME")" &>/dev/null && pwd)"
ROOT=$(cd $HERE/.. && pwd)
RED=$'\033[0;31m'
LIGHTRED=$'\033[1;31m'
NOCOLOR=$'\033[0m'

cd $HERE

#----------------------------------------------------------------------------------------------

valgrind_check() {
	echo -n "${NOCOLOR}"
	if grep -l "$1" $logdir/*.valgrind.log &> /dev/null; then
		echo
		echo "${LIGHTRED}### Valgrind: ${TYPE} detected:${RED}"
		grep -l "$1" $logdir/*.valgrind.log
		echo -n "${NOCOLOR}"
		E=1
	fi
}

valgrind_summary() {
	local logdir="$ROOT/tests/$DIR/logs"

	local leaks_head=0
	for file in $(ls $logdir/*.valgrind.log 2>/dev/null); do
		# If the last "definitely lost: " line of a logfile has a nonzero value, print the file name
		if tac "$file" | grep -a -m 1 "definitely lost: " | grep "definitely lost: [1-9][0-9,]* bytes" &> /dev/null; then
			if [[ $leaks_head == 0 ]]; then
				echo
				echo "${LIGHTRED}### Valgrind: leaks detected:${RED}"
				leaks_head=1
			fi
			echo "$file"
			E=1
		fi
	done

	TYPE="invalid reads" valgrind_check "Invalid read"
	TYPE="invalid writes" valgrind_check "Invalid write"
}

#----------------------------------------------------------------------------------------------

sanitizer_check() {
	if grep -l "$1" $logdir/*.asan.log* &> /dev/null; then
		echo
		echo "${LIGHTRED}### Sanitizer: ${TYPE} detected:${RED}"
		grep -l "$1" $logdir/*.asan.log*
		echo "${NOCOLOR}"
		E=1
	fi
}

sanitizer_summary() {
	local logdir="$ROOT/tests/$DIR/logs"
	if ! TYPE="leaks" sanitizer_check "Direct leak"; then
		TYPE="leaks" sanitizer_check "detected memory leaks"
	fi
	TYPE="buffer overflow" sanitizer_check "dynamic-stack-buffer-overflow"
	TYPE="memory errors" sanitizer_check "memcpy-param-overlap"
	TYPE="stack use after scope" sanitizer_check "stack-use-after-scope"
	TYPE="use after free" sanitizer_check "heap-use-after-free"
	TYPE="signal 11" sanitizer_check "caught signal 11"
}

#----------------------------------------------------------------------------------------------

E=0

DIRS=
if [[ $UNIT == 1 ]]; then
	DIRS+=" ."
fi
if [[ $FLOW == 1 ]]; then
	DIRS+=" pytests"
fi

if [[ $VG == 1 ]]; then
	for dir in $DIRS; do
		DIR="$dir" valgrind_summary
	done
elif [[ -n $SAN ]]; then
	for dir in $DIRS; do
		DIR="$dir" sanitizer_summary
	done
fi

if [[ $E == 0 ]]; then
	echo "# No leaks detected"
fi

exit $E
