#!/bin/bash

# Run this from the top-level vamp-build-and-test directory

## Things to test:
##   the plugin builds!
##   plugin loads
##   passes vamp-plugin-tester tests
##   does not export any unnecessary symbols
##   has valid .cat and .n3

platform=linux
bits=64

reportdir="REPORTS/$platform$bits"
mkdir -p "$reportdir" || exit 1

built="/tmp/built.$$.txt"
testfailed="/tmp/testfailed.$$.txt"
notbuilt="/tmp/notbuilt.$$.txt"
trap 'rm -f "$built" "$testfailed" "$notbuilt"' 0
touch "$built" "$testfailed" "$notbuilt"

configure() {
    dir="$1"
    if [ -f "$dir/configure" ] ; then
	( cd "$dir" ; ./configure ) 2>&1 | tee "$reportdir/$dir.configure.txt"
    fi
}

configure_maybe() {
    dir="$1"
    if [ ! -f "$dir/Makefile" ] ; then
	configure "$dir"
    fi
}

find_makefile() {
    dir="$1"

    for f in \
	Makefile \
	Makefile.$platform \
	Makefile.$platform$bits \
	build/$platform/Makefile \
	build/$platform/Makefile.$platform \
	build/$platform/Makefile.$platform$bits; do
	if [ -f "$dir/$f" ]; then
	    echo $f
	    break
	fi
    done
}

build() {
    dir="$1"
    if configure_maybe "$dir"; then
	mfile=$(find_makefile "$dir")
	if [ -n "$mfile" ]; then
	    make -C "$dir" -f "$mfile" 2>&1 | tee "$reportdir/$dir.build.txt"
	    return ${PIPESTATUS[0]}
	else
	    echo "Failed to find a Makefile in $dir"
	    return 1
	fi
    fi
}

rebuild() {
    dir="$1"
    if configure "$dir"; then
	mfile=$(find_makefile "$dir")
	if [ -n "$mfile" ]; then
	    make -C "$dir" -f "$mfile" clean
	    make -C "$dir" -f "$mfile" 2>&1 | tee "$reportdir/$dir.build.txt"
	    return ${PIPESTATUS[0]}
	else
	    echo "Failed to find a Makefile in $dir"
	    return 1
	fi
    fi
}

run_tester() {
    ##!!! todo: timeout if the plugin takes too long and report as failure?
    dir="$1"
    ids=$(VAMP_PATH="$dir" vamp-plugin-sdk/host/vamp-simple-host --list-ids | sed 's/^vamp://')
    if [ -z "$ids" ]; then
	echo 
	echo "No plugins reported to test in $dir"
	return 1
    else
	for id in $ids; do
	    extra=""
	    if grep -q "^$id\$" METADATA/nondeterministic.txt; then
		extra="-n"
	    fi
	    if ( VAMP_PATH="$dir" vamp-plugin-tester/vamp-plugin-tester "$extra" "$id" 2>&1 | tee "$reportdir/$dir.test.txt" ; exit ${PIPESTATUS[0]} ) ; then
		echo "OK"
	    else
		echo
		echo "Tester failed for id $id: running again with valgrind and verbose for a report..."
		echo "$dir" >> "$testfailed"
		VAMP_PATH="$dir" valgrind vamp-plugin-tester/vamp-plugin-tester -v "$extra" "$id" 2>&1 | tee -a "$reportdir/$dir.test.txt"
		return 1
	    fi
	done
    fi
}

public_symbols() {
    lib="$1"
    nm -g --defined-only "$lib" | awk '{ print $3; }'
}

run_environmental_tests() {
    dir="$1"
    for lib in $dir/*.so; do 
	if public_symbols "$lib" | grep -q vampGetPluginDescriptor; then
	    others=`public_symbols "$lib" | grep -v vampGetPluginDescriptor`
	    if [ -n "$others" ]; then
		count=`echo "$others" | wc -l`
		echo "WARNING: $count extra symbols exported by plugin library"
		#!!! what to do about it?
	    else
		echo "GOOD: library $lib only exports vampGetPluginDescriptor"
	    fi
	else
	    echo "NOTE: found library $lib that is not a Vamp plugin library"
	fi
    done
}

if ! build "vamp-plugin-sdk"; then 
    echo "Failed to build Vamp plugin SDK!"
    exit 1
fi

if ! build "vamp-plugin-tester"; then 
    echo "Failed to build Vamp plugin tester!"
    exit 1
fi

for dir in $(cat .hgsub | grep -v vamp-plugin-sdk | grep -v vamp-plugin-tester | awk '{ print $1; }') ; do
    echo
    echo "Processing: $dir"
    if rebuild "$dir"; then
	echo "$dir" >> "$built"
	run_tester "$dir"
	run_environmental_tests "$dir"
    else
	echo "$dir" >> "$notbuilt"
    fi
done

cat /dev/null > "$reportdir/$dir.summary.txt"

echo
echo "** Successfully built and tested:"
cat "$built" | while read d; do
    if ! grep -q "^$d\$" "$testfailed"; then
	echo "$d"
	echo "Success" >> "$reportdir/$d.summary.txt"
    fi
done | sort

echo
echo "** Built, but failed tests:"
cat "$testfailed" | sort | uniq | while read d; do
    echo "$d"
    echo "Built successfully, but failed tests" >> "$reportdir/$d.summary.txt"
done

echo
echo "** Failed to build:"	    
cat "$notbuilt" | sort | while read d; do
    echo "$d"
    echo "Failed to build" >> "$reportdir/$d.summary.txt"
done

echo
