Tutorial: Moodle VPL -- Test Elapsed Time of Program
--D. Thiebaut (talk) 21:15, 24 October 2014 (EDT)
Contents |
This VPL activity tests a Java program and verifies that it spends more than a predefined amount of seconds to run.
vpl_run.sh
#! /bin/bash
# D. Thiebaut
cat > vpl_execution <<EEOOFF
#! /bin/bash
prog1=Hw5_2
javac \${prog1}.java > /dev/null
if ((\$? > 0)); then
echo "Error compiling your program"
exit
fi
Ns=(7 8 9 10 12 14)
CORRECTOUTPUTS=(40 92 352 724 14200 365596)
for i in \`seq 0 5\`; do
echo ""
N=\${Ns[\$i]}
echo "Test # \$i"
echo "N = \$N"
#echo "The correct output is: \${CORRECTOUTPUTS[\$i]}"
echo "Your program output:"
echo "java \${prog1} \$N"
java \${prog1} \$N
done
echo ""
echo "Done!"
EEOOFF
chmod +x vpl_execution
vpl_evaluate.sh
#! /bin/bash
# D. Thiebaut
cat > vpl_execution <<EEOOFF
#! /bin/bash
#set -x
# --- program tested (no extension) ---
prog1=Hw5_2
# --- grades
gradeNotCompile=20
gradeCompileNoGoodOutput=30
gradeIncrement=12 # (100-30)/ number of tests
gradePenaltyTooFast=50
# --- compile student program ---
javac \${prog1}.java
if ((\$? > 0)); then
echo "Comment :=>> Error compiling your program"
echo "Grade :=>> \$gradeNotCompile"
exit
fi
# --- minimum grade if not passing any test ---
grade=\$gradeCompileNoGoodOutput
# =================================================
Ns=(7 8 9 10 12 14)
CORRECTOUTPUTS=(40 92 352 724 14200 365596)
NOTESTS=6
# =================================================
# function that prints the difference between user and expected output
incorrectOutput() {
if [ "\$1" ]; then # if there's a parameter
i=\$1
echo "Comment :=>>- Incorrect output."
#--- display test file ---
echo "Comment :=>>- Your program was tested with:"
echo "<|--"
cat data\${i}.txt
echo "--|>"
echo "Comment :=>> ---------------"
echo "Comment :=>>- Your output was: "
echo "Comment :=>> ---------------"
echo "<|--"
cat user.out.org
echo "--|>"
echo ""
echo "Comment :=>> ---------------"
echo "Comment :=>>- Debug your program, and try again!"
echo "Comment :=>> ---------------"
#echo "<|--"
#cat data\${i}.out
#echo "--|>"
fi
}
# function that tells user of program crash or infinite loop, and what the test was.
timeoutOutput() {
if [ "\$1" ]; then # if there's a parameter
i=\$1
echo "Comment :=>>- Your program has timed out or crashed."
#--- display test file ---
echo "Comment :=>>- Your program tested with:"
echo "<|--"
cat data\${i}.txt
echo "--|>"
fi
}
# function that removes non-digits, extra spaces, and extra blank lines from text file.
cleanup () {
if [ "\$1" ]; then # if there's a parameter
#--- remove non numbers and non minus---
cat \$1 | sed 's/[^0-9*.0-9\ -]*//g' > dummy.out
mv dummy.out \$1
#--- remove multiple spaces ---
cat \$1 | sed 's/ */ /g' > dummy.out
mv dummy.out \$1
#--- remove blank lines ---
cat \$1 | sed '/^\s*\$/d' > dummy.out
mv dummy.out \$1
fi
}
#---------------------------------------------------------
# Start testing here
#---------------------------------------------------------
STARTTIME=\$(date +%s)
NOTESTS_1=\`expr \$NOTESTS - 1 \`
for i in \`seq 0 \$NOTESTS_1 \`; do
# ==============================================
# TEST i
# timeout code from
# http://stackoverflow.com/questions/5161193/bash-script-that-kills-a-child-process-after-a-given-timeout
# ==============================================
#--- run program, capture output, display to student ---
N=\${Ns[\$i]}
echo "Comment :=>>-TEST \$i"
echo "Comment :=>> N = \$N"
echo \$N > data\${i}.txt
timeout 50 java \${prog1} \$N &> user.out
retcode=\$?
#--- if we killed the waiter, everything is good ---
if [ \$retcode -eq 124 ]; then
echo "Comment :=>>-Your program has stopped working or was taking TOO LONG!"
timeoutOutput \$i
continue
else
echo "Comment :=>>-Your program ran to completion."
fi
cp user.out user.out.org
#--- copy expected output in output file
echo \${CORRECTOUTPUTS[\$i]} > data\${i}.out
#--- remove non numbers, space and extra lines from user.out ---
#--- and from datai.out
cleanup user.out
cleanup data\${i}.out
#--- compute difference ---
diff -y -w --ignore-all-space user.out data\${i}.out > diff.out
#echo "----- diff.out ------"
#cat diff.out
#echo "---------------------"
#diff -y -w --ignore-all-space user.out data\${i}.out > diff.out
#--- reject if different ---
if ((\$? > 0)); then
incorrectOutput \$i
# --------------------- REWARD IF CORRECT OUTPUT -----------------
else
#--- good output ---
echo "Comment :=>>- Congrats, your output is correct."
echo "Comment :=>> --------------------------------."
echo "<|--"
cat user.out.org
echo "--|>"
grade=\$((grade+gradeIncrement))
fi
done
ENDTIME=\$(date +%s)
ELAPSEDTIME=\$((ENDTIME-STARTIME))
# program is too fast. Remove 50 points
if [[ (( ELAPSEDTIME < 5 )) ]]; then
#echo "less than 10 sec"
grade=\$((grade-gradePenaltyTooFast))
if (( grade < 0 )); then
grade=0
fi
fi
# =================================================
# Report grade
if (( grade > 100 )); then
grade=100
fi
echo "Grade :=>> \$grade"
EEOOFF
chmod +x vpl_execution