#!/usr/bin/env -S bats --report-formatter junit --formatter tap -j 8
# -*-sh-*-

source ../../../common/test_helper_functions.bash || exit 1
source ../../../common/functions || exit 1

if [ -s ../../../common/TEST_ENV ]; then
	source ../../../common/TEST_ENV
fi

setup_file() {
	PKG=VALGRIND
	MODULE=valgrind
	TESTNAME="dev-tools/Valgrind"
	HEADER=valgrind/valgrind.h
	check_compiler_family CC CXX FC

	export PKG MODULE TESTNAME HEADER CC CXX FC
}

setup() {
	OUTPUT="$(mktemp)"

	export OUTPUT
}

teardown() {
	rm -f "${OUTPUT}"
}

@test "[${TESTNAME}] Verify ${MODULE} module is loaded and matches rpm version ($LMOD_FAMILY_COMPILER)" {
	module list "${MODULE}" | grep "1) ${MODULE}" >&"${OUTPUT}" || exit 1
	run grep "${MODULE}" "${OUTPUT}"
	assert_success

	# check version against rpm
	local version
	version="$(rpm -q --queryformat='%{VERSION}\n' "${MODULE}${DELIM}")"
	run cat "${OUTPUT}"
	assert_output "  1) ${MODULE}/${version}"
}

@test "[${TESTNAME}] Verify ${PKG}_DIR is defined and directory exists ($LMOD_FAMILY_COMPILER)" {
	PKG_DIR="${PKG}_DIR"

	if [ -z "${!PKG_DIR}" ]; then
		flunk "env setting ${PKG_DIR} not defined"
	fi

	if [ ! -d "${!PKG_DIR}" ]; then
		flunk "directory ${!PKG_DIR} does not exist"
	fi
}

@test "[${TESTNAME}] Verify availability of ${MODULE} binary ($LMOD_FAMILY_COMPILER)" {
	run which valgrind
	assert_success
}

# ----------
# Man pages
# ----------

@test "[${TESTNAME}] Verify availability of man page ($LMOD_FAMILY_COMPILER)" {
	PKG_DIR="${PKG}_DIR"

	if [ -z "${!PKG_DIR}" ]; then
		flunk "env setting ${PKG_DIR} not defined"
	fi

	if [ ! -d "${!PKG_DIR}" ]; then
		flunk "directory ${!PKG_DIR} does not exist"
	fi

	run man -w "${MODULE}"
	assert_success
	assert_output "${!PKG_DIR}/share/man/man1/valgrind.1"
}

# --------------
# Include Tests
# --------------

@test "[${TESTNAME}] Verify module ${PKG}_INC is defined and exists ($LMOD_FAMILY_COMPILER)" {
	INC="${PKG}_INC"

	if [ -z "${!INC}" ]; then
		flunk "${PKG}_INC directory not defined"
	fi

	if [ ! -d "${!INC}" ]; then
		flunk "directory ${!INC} does not exist"
	fi
}

@test "[${TESTNAME}] Verify header file is present in ${PKG}_INC ($LMOD_FAMILY_COMPILER)" {
	INC="${PKG}_INC"

	if [ -z "${!INC}" ]; then
		flunk "${PKG}_INC directory not defined"
	fi

	if [ ! -s "${!INC}/${HEADER}" ]; then
		flunk "${HEADER} file does not exist"
	fi
}

# Execution Test(s)

@test "[${TESTNAME}] Callgrind test ($LMOD_FAMILY_COMPILER)" {
	if [ ! -x ./simwork ]; then
		flunk "./simwork binary does not exist"
	fi

	rm -f callgrind.out*

	run valgrind --tool=callgrind ./simwork
	run ls -l callgrind.out*
	assert_success

	rm -f callgrind.out*
}

@test "[${TESTNAME}] Memcheck test ($LMOD_FAMILY_COMPILER)" {
	if [[ "${LMOD_FAMILY_COMPILER}" =~ "acfl" ]]; then
		skip "arm compiler currently breaks valgrind"
	fi

	# Clean program that should run without incident
	if [ ! -x ./hello ]; then
		flunk "./hello binary does not exist"
	fi
	run valgrind -q --error-exitcode=1 ./hello
	assert_success

	# Program with memory error that valgrind should detect
	if [ ! -x ./badfree ]; then
		flunk "./badfree binary does not exist"
	fi
	run valgrind -q --error-exitcode=1 ./badfree
	assert_failure
}
