# The Evaluator -- Shell Function Library # (c) 2001 Martin Mares # General settings shopt -s dotglob # Logging functions. # File handles used: fd1=log, fd2=progress function log-init { exec >>$TDIR/log HAVE_LOG=1 } function pstart { echo >&2 -n "$@" } function pcont { echo >&2 -n "$@" } function pend { echo >&2 "$@" } function die { echo >&2 "$@" [ -n "$HAVE_LOG" ] && echo "Fatal error: $@" exit 1 } # Sandbox subroutines function box-init { pstart "Preparing sandbox... " [ -n "$TEST_USER" ] || die "TEST_USER not set. Please fix." if [ $TEST_USER == $EVAL_USER ] ; then pcont "running locally (INSECURE), " BOXDIR=box BOXCMD=bin/box mkdir -p box else pcont "used account $TEST_USER, " BOXDIR=$MO_ROOT/$TEST_USER BOXCMD=bin/box-$TEST_USER fi [ -d $BOXDIR -a -f $BOXCMD ] || die "Sandbox set up incorrectly" BOXCMD="$BOXCMD -c$BOXDIR" echo "Sandbox directory: $BOXDIR" echo "Sandbox command: $BOXCMD" box-clean pend "OK" } function box-clean { [ -n "$BOXCMD" ] || die "box-init not called" rm -rf $BOXDIR/* } # Initialization of testing directories function dir-init { pstart "Initializing... " HDIR=. PDIR=problems/$PROBLEM SDIR=solutions/$CONTESTANT/$PROBLEM TDIR=testing/$CONTESTANT/$PROBLEM [ -d $PDIR ] || die "Problem $PROBLEM not known" [ -d $SDIR ] || die "Solution of $PROBLEM not found" mkdir -p $TDIR rm -rf $TDIR cp -a $SDIR $TDIR cat >$TDIR/log <$TDIR/points pend "OK" } # Locating source file in SDIR, pass name in SRCN (without path) and extension in SRCEXT function locate-source { pstart "Finding source... " SBASE=${1:-$PROBLEM} for a in $EXTENSIONS ; do if [ -f $SDIR/$SBASE.$a ] ; then [ -z "$SRCN" ] || die "Multiple source files found: $SDIR/$PROBLEM.$a and $SDIR/$SRCN. Please fix." SRCN=$SBASE.$a SRCEXT=$a fi done [ -n "$SRCN" ] || die "NOT FOUND" pend $SRCN echo "Found source file: $SDIR/$SRCN" } # Compilation (compile SDIR/SRCN with PDIR/EXTRAS to EXE=TDIR/PROBLEM) function compile { pstart "Compiling... " cp -a $SDIR/$SRCN $TDIR/$SRCN if [ -n "$EXTRAS" ] ; then echo "Extras: $EXTRAS" for a in $EXTRAS ; do cp $PDIR/$a $TDIR/ ; done fi box-clean for a in $SRCN $EXTRAS ; do cp $TDIR/$a $BOXDIR/ ; done SRC=$SRCN EXE=$PROBLEM CCMD=COMP_$SRCEXT CCMD=`eval echo ${!CCMD}` COMP_SANDBOX_OPTS=`eval echo $COMP_SANDBOX_OPTS` echo "Compiler command: $CCMD" echo "Compiler sandbox options: $COMP_SANDBOX_OPTS" eval $COMP_SANDBOX_INIT echo "Compiler input files:" ls -Al $BOXDIR echo "Compiler output:" if ! $BOXCMD $COMP_SANDBOX_OPTS -- $CCMD 2>$TDIR/compile.out ; then COMPILE_MSG="`cat $TDIR/compile.out`" pend "FAILED: $COMPILE_MSG" echo "$COMPILE_MSG" return 1 fi cat $TDIR/compile.out rm $TDIR/compile.out echo "Compiler output files:" ls -Al $BOXDIR if [ ! -f $BOXDIR/$PROBLEM ] ; then pend "FAILED: Missing executable file" echo "Missing executable file" return 1 fi EXE=$TDIR/$PROBLEM cp -a $BOXDIR/$PROBLEM $EXE echo "Compiled OK, result copied to $EXE" pend "OK" } # Running of test program according to current task type function test-run { test-run-$TASK_TYPE } # Running of test program with file input/output function test-run-file { pcont " " box-clean echo "Executable file: $TDIR/$PROBLEM" cp $TDIR/$PROBLEM $BOXDIR/ echo "Input: $TDIR/$PROBLEM" ln $PDIR/$TEST.in $TDIR/$TEST.in cp $PDIR/$TEST.in $BOXDIR/$PROBLEM.in eval $SANDBOX_INIT echo "Input files:" ls -Al $BOXDIR pcont " " echo "Timeout: $TIME_LIMIT s" echo "Memory: $MEM_LIMIT KB" BOXOPTS=`eval echo $TEST_SANDBOX_OPTS` echo "Sandbox options: $BOXOPTS" if ! $BOXCMD $BOXOPTS -- ./$PROBLEM 2>$TDIR/exec.out ; then TEST_MSG="`head -1 $TDIR/exec.out`" pend "$TEST_MSG" cat $TDIR/exec.out rm $TDIR/exec.out echo >>$PTSFILE "0 $TEST_MSG" return 1 fi cat $TDIR/exec.out rm $TDIR/exec.out echo "Output files:" ls -Al $BOXDIR if [ ! -s $BOXDIR/$PROBLEM.out ] ; then pend "No output file." echo "No output file." echo >>$PTSFILE "0 No output." return 1 fi cp $BOXDIR/$PROBLEM.out $TDIR/$TEST.out } # Running of interactive test programs function test-run-interactive { pcont " " box-clean echo "Executable file: $TDIR/$PROBLEM" cp $TDIR/$PROBLEM $BOXDIR/ echo "Input: $TDIR/$PROBLEM" ln $PDIR/$TEST.in $TDIR/$TEST.in cp $PDIR/$TEST.in $BOXDIR/$PROBLEM.in eval $SANDBOX_INIT echo "Input files:" ls -Al $BOXDIR pcont " " echo "Timeout: $TIME_LIMIT s" echo "Memory: $MEM_LIMIT KB" BOXOPTS=`eval echo $TEST_SANDBOX_OPTS` echo "Sandbox options: $BOXOPTS" ICCMD=`eval echo $IA_CHECK` echo "Interactive checker: $ICCMD" if ! $HDIR/bin/iwrapper $BOXCMD $BOXOPTS -- ./$PROBLEM @@ $ICCMD 2>$TDIR/exec.out ; then TEST_MSG="`head -1 $TDIR/exec.out`" pend "$TEST_MSG" cat $TDIR/exec.out rm $TDIR/exec.out echo "$TEST_MSG" echo >>$PTSFILE "0 $TEST_MSG" return 1 fi cat $TDIR/exec.out rm $TDIR/exec.out } # Syntax checks function syntax-check { [ -n "$SYNTAX_CHECK" ] || return 0 pcont " " SCHECK=`eval echo $SYNTAX_CHECK` echo "Syntax check command: $SCHECK" eval $SCHECK && return 0 pend "Wrong syntax." echo "Wrong syntax." echo >>$PTSFILE "0 Wrong syntax." return 1 } # Output checks function output-check { [ -n "$OUTPUT_CHECK" ] || return 0 pcont " " [ -f $PDIR/$TEST.out ] && ln $PDIR/$TEST.out $TDIR/$TEST.ok OCHECK=`eval echo $OUTPUT_CHECK` echo "Output check command: $OCHECK" eval $OCHECK && return 0 pend "Wrong answer." echo "Wrong answer." echo >>$PTSFILE "0 Wrong answer." return 1 } # Setup of public commands function public-setup { HDIR=$MO_PUBLIC PDIR=$MO_PUBLIC/problems/$PROBLEM SDIR=. TDIR=~/.test [ -d $PDIR ] || die "Unknown problem $PROBLEM" pstart "Initializing... " mkdir -p $TDIR rm -rf $TDIR/* BOXDIR=~/.box mkdir -p $BOXDIR rm -rf $BOXDIR/* BOXCMD="$MO_PUBLIC/bin/box -c$BOXDIR" exec >log pend "OK (see 'log' for details)" } # Locate output of open data problem, test case TEST function open-locate { [ -f $PDIR/$TEST.in ] || die "Unknown test $TEST" SRCN=$SDIR/$PROBLEM$TEST.out [ -f $SRCN ] || die "Output file $SRCN not found" }