#!/usr/bin/env bash # This script runs the regression tests in src/regression. # It also compiles the tests in benchmark/tests # set -e ParApp-Spawn () { local Lock="$1" local Unlock="$2" local Signal="$3" local liveFile=$4 shift 4 $@ || true $Lock local liveProcs=$(cat $liveFile) echo $((liveProcs-1)) > $liveFile $Signal $Unlock } ParApp () { local lockFile=$(tempfile) local condFile=$(tempfile) local liveFile=$(tempfile) local Clean="rm -f $lockFile $condFile $liveFile" local Lock="lockfile $lockFile" local Unlock="rm -f $lockFile" local Wait="lockfile -1 $condFile" local Signal="rm -f $condFile" $Clean $Wait echo 0 > $liveFile local liveProcs local maxProcs=$1 local command=$2 shift 2 while [ $# -gt 0 ]; do $Lock while [ $(cat $liveFile) -ge $maxProcs ]; do $Unlock && $Wait && $Lock done liveProcs=$(cat $liveFile) echo $((liveProcs+1)) > $liveFile $Unlock ParApp-Spawn "$Lock" "$Unlock" "$Signal" $liveFile $command "$1" & shift done $Lock while [ $(cat $liveFile) -gt 0 ]; do $Unlock && $Wait && $Lock done $Unlock $Clean } name=`basename "$0"` usage () { echo >&2 "usage: $name [-cross target] [-parallel n] [-resume test] [-run-only target] [-short] [-test-reg reg] [mlton flags ...]" exit 1 } parallel=1 cross='false' fail='false' resume='true' resumeTest='nil' runOnly='false' short='false' testReg='false' declare -a testRegs declare -a flags declare -a extraFlags flags[${#flags[@]}]="-type-check" flags[${#flags[@]}]="true" while [ "$#" -gt 0 ]; do case "$1" in -cross) cross='true' shift if [ "$#" = 0 ]; then usage fi crossTarget="$1" shift ;; -fail) fail='true' shift ;; -parallel) if ! [ $2 -gt 0 ]; then usage fi parallel=$2 shift 2 ;; -resume) resume='false' shift if [ "$#" = 0 ]; then usage fi resumeTest="$1" shift ;; -run-only) runOnly='true' shift if [ "$#" = 0 ]; then usage fi crossTarget="$1" shift ;; -short) short='true' shift ;; -test-reg) testReg='true' shift if [ "$#" = 0 ]; then usage fi testRegs[${#testRegs[@]}]="$1" shift ;; *) flags[${#flags[@]}]="$1" shift ;; esac done dir=`dirname "$0"` src=`cd "$dir/.." && pwd` bin="$src/build/bin" lib="$src/build/lib" mlton="$bin/mlton" if $cross; then flags[${#flags[@]}]="-target" flags[${#flags[@]}]="$crossTarget" flags[${#flags[@]}]="-stop" flags[${#flags[@]}]="g" fi cont='callcc.sml callcc2.sml callcc3.sml once.sml' flatArray='finalize.sml flat-array.sml flat-array.2.sml' intInf='conv.sml conv2.sml fixed-integer.sml harmonic.sml int-inf.*.sml slow.sml slower.sml smith-normal-form.sml' signal='finalize.sml signals.sml signals2.sml suspend.sml weak.sml' thread='thread0.sml thread1.sml thread2.sml mutex.sml prodcons.sml same-fringe.sml timeout.sml' world='world1.sml world2.sml world3.sml world4.sml world5.sml world6.sml' tmp=/tmp/z.regression.$$ PATH="$bin:$src/bin/.:$PATH" eval `"$lib/platform"` compFail () { echo "compilation of $f failed with ${flags[*]}" } "$mlton" -verbose 1 || echo 'no mlton present' echo "flags = ${flags[*]}" cd "$src/regression" FailTest () { local f=$1 echo "testing $f" ( "$mlton" "${flags[@]}" -stop tc "$f" >/dev/null 2>&1 && echo "compilation of $f should have failed but did not" ) || true } if $fail; then ParApp $parallel FailTest fail/*.sml exit 0 fi forMinGW='false' if [ `host-os` = mingw ]; then forMinGW='true' fi case $crossTarget in *mingw) forMinGW='true' ;; esac Test () { local f=$1 f=`basename "$f" .sml` if ! ($resume); then if [ "$f" == "$resumeTest" ]; then resume='true' else return fi fi if ($testReg); then skip='true' for (( i = 0 ; $i < ${#testRegs[@]} ; i++ )); do if [ "$f" = "${testRegs[$i]}" ]; then skip='false' fi done if ($skip); then return fi fi case `host-os` in cygwin|mingw) case "$f" in echo|signals|socket|suspend|textio.2|world*) return ;; esac ;; esac case `host-os` in mingw) case "$f" in cmdline|command-line|filesys|posix-exit|signals2|unixpath) return ;; esac esac case "$f" in serialize) return ;; esac echo "testing $f" unset extraFlags case "$f" in exnHistory*) extraFlags[${#extraFlags[@]}]="-const" extraFlags[${#extraFlags[@]}]="Exn.keepHistory true" ;; esac if (! $runOnly); then mlb="$f.mlb" echo "\$(SML_LIB)/basis/basis.mlb \$(SML_LIB)/basis/mlton.mlb \$(SML_LIB)/basis/sml-nj.mlb ann \"allowFFI true\" \"allowOverload true\" \"nonexhaustiveMatch ignore\" \"redundantMatch ignore\" in $f.sml end" >"$mlb" "$mlton" "${flags[@]}" "${extraFlags[@]}" -output "$f" "$mlb" if [ "$?" -ne '0' ] || ((! $cross) && [ ! -x "$f" ]); then compFail "$f" fi rm "$mlb" else case "$crossTarget" in *mingw) libs='-lws2_32 -lkernel32 -lpsapi -lnetapi32' ;; *solaris) libs='-lnsl -lsocket -lrt' ;; *) libs='' ;; esac libs="-lmlton -lgmp $libs -lgdtoa -lm" # Must use $f.[0-9].[cS], not $f.*.[cS], because the # latter will include other files, e.g. for finalize, # it will also include finalize.2. This happens only # when running cross regressions, which builds all the # C files and saves them in this directory. files="$f.[0-9].[cS]" if [ 0 -ne `ls $f.[0-9][0-9].[cS] 2>/dev/null | wc -l` ]; then files="$files $f.[0-9][0-9].[cS]" fi gcc -o "$f" -w -O1 \ -I "../build/lib/include" \ -I "../build/lib/$crossTarget/include" \ -L"../build/lib/$crossTarget" \ -L/usr/pkg/lib \ -L/usr/local/lib \ $files $libs fi if [ ! -r "$f".nonterm -a $cross = 'false' -a -x "$f" ]; then nonZeroMsg='Nonzero exit status.' if $forMinGW; then nonZeroMsg="$nonZeroMsg"'\r' fi local tmp=$(tempfile) ( "./$f" || echo -e "$nonZeroMsg" ) >$tmp 2>&1 if [ -r "$f.ok" ]; then compare="$f.$HOST_ARCH-$HOST_OS.ok" if [ ! -r $compare ]; then compare="$f.ok" fi if $forMinGW; then newcompare="$f.sed.ok" sed $'s/$/\r/' <"$compare" > "$newcompare" compare="$newcompare" fi if ! diff "$compare" "$tmp"; then echo "difference with ${flags[*]} ${extraFlags[*]}" fi fi rm $tmp fi } ParApp $parallel Test *.sml if $cross || $runOnly || $short || $testReg ; then exit 0 fi mmake clean >/dev/null cd "$src/benchmark/tests" BenchmarkTest () { local f=$1 f=`basename "$f" .sml` tmpf="/tmp/$f.$$" case "$f" in fxp|hamlet) echo "skipping $f" ;; *) echo "testing $f" echo "val _ = Main.doit 0" | cat "$f.sml" - > "$tmpf.sml" $mlton -output "$tmpf" "${flags[@]}" \ -default-ann 'nonexhaustiveMatch ignore'\ -default-ann 'redundantMatch ignore' \ "$tmpf.sml" if [ $? -ne 0 ]; then compFail "$f" fi rm -f "$tmpf" "$tmpf.sml" ;; esac } ParApp $parallel BenchmarkTest *.sml mmake clean >/dev/null cd "$src" ProgramTest () { local f=$1 tmpf="/tmp/$f.$$" cd "$src/$f" echo "testing $f" mmake -W "$f" >/dev/null "$mlton" "${flags[@]}" -output "$tmpf" "$f.mlb" if [ $? -ne 0 ]; then compFail "$f" fi rm -f "$tmpf" } ParApp $parallel ProgramTest mllex mlyacc mlprof rm -f "$tmp"