#!/bin/bash

export CFLAGS="$CFLAGS"
export MAKEFLAGS="$MAKEFLAGS --no-print-directory"
export BROWSER="firefox"

help_all() {
	echo 
	echo "Usage: check <command>"
	echo 
	echo "Commands:"
	echo 
	echo "  ansi            Check using ansi compiler option"
	echo "  sysv            Check using sys-v semaphores"
	echo "  nosection       Check without gcc __attribute__(section)"
	echo "  noepoll         Check using poll (not epoll)"
	echo "  nogettime       Check without gettime()"
	echo "  bsd             Check with a bsd-like config"
	echo "  mac             Check with a mac/darwin-like config"
	echo "  dist            do make distcheck"
	echo "  rpm             Run rpmlint"
	echo "  mock            Test doing a mock build"
	echo "  coverity        Run coverity"
	echo "  clang           Run clang-analyze"
	echo "  abi             Check abi compatibility"
	echo "  api_sanity      api sanity test"
	echo 
	echo "  help            This help"
	echo 
	exit 1
}

if [ $# -lt 1 ]
then
    help_all
fi

command=$1
shift
args="$@"

if [ -n "$(git rev-parse)" ] ; then
        perror "Must be inside a git repository to work"
        exit 1
fi

up=$(git rev-parse --show-cdup)
if [ "x$up" == "x" ] ; then
	up="."
fi
cd $up

set -e
if [ ! -e build-aux/install-sh ]
then
	./autogen.sh
fi
if [ ! -e Makefile ]
then
	./configure --quiet
fi

check() {
	options="$1 --enable-debug --enable-slow-tests --enable-fatal-warnings --quiet"
	echo "./configure $options"
	echo "ENV CFLAGS=\"$CFLAGS\""
	echo "ENV MAKEFLAGS=\"$MAKEFLAGS\""
	( ./configure $options )
	make check
	if [ $? -ne 0 ]
	then
		echo "======================"
		echo failed: $1
		echo "======================"
		if [ -f tests/test-suite.log ]
		then
			cat tests/test-suite.log
		fi
		exit 1
	fi
}

check_ansi() {
	echo "checking ansi"
	echo "==============="
	check "--enable-ansi"
}

check_nosection() {
	echo "checking nosection"
	echo "======================="
	# no __attribute__((section))
	# NOTE: alternatively CPPFLAGS=-DQB_KILL_ATTRIBUTE_SECTION, but
	#       that won't shortcut many initial/configure decisions
	check "ac_cv_link_attribute_section=no"
}

check_sysv() {
	# use sys-v semaphores
	echo "checking sysv"
	echo "======================="
	ORIG_CFLAGS=$CFLAGS
	export CFLAGS="$CFLAGS -DDISABLE_POSIX_THREAD_PROCESS_SHARED"
	check
	export CFLAGS=$ORIG_CFLAGS
}

check_nogettime() {
	# no clock_gettime
	echo "checking nogettime"
	echo "======================="
	check "ac_cv_func_clock_gettime=no"
}

check_noepoll() {
	# no epoll
	echo "checking noepoll"
	echo "======================="
	check "ac_cv_func_epoll_create1=no ac_cv_func_epoll_create=no"
}

check_bsd() {
	# bsd-like
	echo "checking bsd"
	echo "======================="
	ORIG_CFLAGS=$CFLAGS
	check "ac_cv_func_sem_timedwait=no ac_cv_func_clock_gettime=no ac_cv_func_epoll_create1=no ac_cv_func_epoll_create=no"
	export CFLAGS=$ORIG_CFLAGS
}

check_mac() {
	# mac-like
	echo "checking mac"
	echo "======================="
	ORIG_CFLAGS=$CFLAGS
	export CFLAGS="$CFLAGS -DDISABLE_POSIX_THREAD_PROCESS_SHARED"
	check "ac_cv_func_clock_gettime=no ac_cv_func_epoll_create1=no ac_cv_func_epoll_create=no ac_cv_link_attribute_section=no"
	export CFLAGS=$ORIG_CFLAGS
}

check_dist() {
	# normal configure with distcheck
	echo "checking dist"
	echo "======================"
	set +e
	./configure --quiet
	make distcheck
	set -e
}

check_rpm() {
	echo "checking rpm building"
	echo "======================"
	set +e
	make maintainer-clean
	./autogen.sh
	./configure --quiet
	make rpm
	echo
	sudo rpm -Uvf --force libqb-*.rpm
	echo rpmlint libqb
	rpmlint libqb
	echo rpmlint libqb-debuginfo
	rpmlint libqb-debuginfo
	echo rpmlint libqb-devel
	rpmlint libqb-devel
	set -e
}


check_mock() {
	echo "checking mock building"
	echo "======================"
	set +e
	make maintainer-clean
	rm -f *.rpm
	./autogen.sh
	./configure --quiet
	make srpm
	mock --no-clean --rebuild *.src.rpm
}

check_coverity() {
	echo "checking coverity"
	echo "======================"
	make clean
	cov-build --dir=cov make
	cov-analyze --dir cov \
		--concurrency \
		--all \
		--aggressiveness-level high \
		--security \
		--wait-for-license
	cov-format-errors --dir cov
}

check_clang() {
	if [ ! -f /usr/libexec/clang-analyzer/scan-build/ccc-analyzer ]
	then
		echo try installing clang-analyze
		exit 1
	fi
	echo "checking clang"
	echo "===================="
	make clean

	./configure \
		CC=/usr/libexec/clang-analyzer/scan-build/ccc-analyzer \
		CXX=/usr/libexec/clang-analyzer/scan-build/c++-analyzer
	make check
}

check_abi() {
	# XXX abi-compliance-checker >= 2 will likely require equivalent of
	#     https://github.com/lvc/abi-compliance-checker/pull/70
	ver1=$1
	ver2=$2
	if [ -z "$ver1" ] ; then
		echo need two versions.
		exit 1
	fi
	if [ -z "$ver2" ] ; then
		echo need two versions.
		exit 1
	fi

	TMPL=build-aux/abi-check-templ.xml
	checker=abi-compliance-checker
	if abi-compliance-checker -info | grep -Fqe '-cxx-incompatible'; then
		checker="${checker} -cxx-incompatible"
	fi

	mkdir -p abi_dumps/libqb
	# ABICC only: current script always accompanied with current template
	#for v in $ver1 $ver2; do cp "${TMPL}" "abi_dumps/libqb/${v}.tmpl"; done

	for v in $ver1 $ver2
	do
		p=$(pwd)_inst_${v}
		t=v${v}
		echo "== Version ${v} =="
		if [ ! -f "abi_dumps/libqb/libqb_${v}.abi.tar.gz" ]
		then
			git checkout "${t}"
			./autogen.sh
			# XXX still complains about missing -Og (-O0 is used)
			./configure --enable-debug
			make
			make install DESTDIR="${p}"
			lib_suffix=$(cut -c 1-32 "${p}/usr/lib64/libqb.so" \
			             | sed -n 's/^INPUT(libqb\.so\([^)]*\).*$/\1/p;q')
			# this is currently recommended way of using abi-dumper
			# instead of relying on internal processing with ABICC
			# itself (still kept around for reference below)
			abi-dumper -loud -debug "${p}/usr/lib64/libqb.so${lib_suffix}" \
			  -vnum "${v}" -o "abi_dumps/libqb/libqb_${v}.abi.tar.gz"

			# former approach of relying solely on ABICC (XXX -lang C)
			#skiplib_cmt=
			#[ -n "${lib_suffix}" ] || skiplib_cmt='#'
			#sed -e "s|@PREFIX@|${p}|" \
			#    -e "s|@VERSION@|${v}|" \
			#    -e "s|@SKIPLIB_CMT@|${skiplib_cmt}|" \
			#    -e "s|@LIB_SUFFIX@|${lib_suffix}|" \
			#    "abi_dumps/libqb/${v}.tmpl" > "abi_dumps/libqb/${v}.xml"
			#rm -f "abi_dumps/libqb/${v}.tmpl"
			#${checker} -l libqb -dump_abi "abi_dumps/libqb/${v}.xml" \
			#    -dump-path "abi_dumps/libqb/libqb_${v}.abi.tar.gz"
		fi
	done

	# Don't exit if there were incompatible ABI changes.
	set +e
	$checker -l libqb \
	   -d1 abi_dumps/libqb/libqb_$ver1.abi.tar.gz \
	   -d2 abi_dumps/libqb/libqb_$ver2.abi.tar.gz
	set -e

	$BROWSER file://`pwd`/compat_reports/libqb/$ver1\_to_$ver2/compat_report.html

	git checkout master
}

check_api_sanity() {
	make
	export CFLAGS="-Wall -ggdb2"
	api-sanity-checker -l libqb -d build-aux/api-auto-test.xml -gen -build -run
	$BROWSER file://`pwd`/test_results/libqb/master/test_results.html
	$BROWSER file://`pwd`/test_results/libqb/master/test_results.html
}

check_all() {
	check_ansi
	check_nosection
	check_sysv
	check_noepoll
	check_nogettime
	check_bsd
	check_dist
	check_rpm
}


case $command in
	help)
	help_all $args
	;;
	ansi)
		check_ansi
	;;
	nosection)
		check_nosection
	;;
	sysv)
		check_sysv
	;;
	noepoll)
		check_noepoll
	;;
	nogettime)
		check_nogettime
	;;
	bsd)
		check_bsd
	;;
	mac)
		check_mac
	;;
	rpm)
		check_rpm
	;;
	mock)
		check_mock
	;;
	dist)
		check_dist
	;;
	coverity)
		check_coverity
	;;
	clang)
		check_clang
	;;
	abi)
		check_abi $args
	;;
	api_sanity)
		check_api_sanity
	;;
	all)
		check_all
	;;
	*)
		help_all
	;;
esac
cd -
exit 0
