Tutorial: Moodle VPL -- Catching Java Programs that Hung

From dftwiki3
Jump to: navigation, search

--D. Thiebaut (talk) 14:53, 28 September 2014 (EDT)


MoodleVPLLogo.png



Moodle VPL Tutorials



This VPL module loops through different tests to evaluate a Java program. It also has a time-out feature in case the java program goes into an infinite loop.


Setup



Execution Files


vpl_run.sh


#! /bin/bash
# D. Thiebaut

cat > vpl_execution <<EEOOFF
#! /bin/bash
 
prog1=Hw3_2
 
javac \${prog1}.java 
 
if ((\$? > 0)); then
     echo "Error compiling your program"
     exit
fi
 
# --- create test input files ---
cat > data1.txt <<EOF
Cardiff Bute Park
Location 3176E 1773N, 9 metres amsl
Estimated data is marked with a * after the value.

   yyyy  mm   tmax    tmin      af    rain     sun
              degC    degC    days      mm   hours
   1977   9   18.3     8.1       0    48.6   117.9
   1977  10   15.4     9.0       0    76.0    80.4
   1977  11   10.3     4.7       4   147.9    76.4
   1977  12    9.6     4.6       2    88.0    25.6
   1978   1    7.5     2.0       6   134.1    64.7
   1978   2    6.2     0.9      13   134.1    56.9
...
   2009   7   20.2    13.1       0   194.1     ---
   2009   8   20.7    ---      0    76.0     120.5
   2009   9   19.1    10.6       0    34.7     ---
   2009  10   16.3     8.6       0    73.6     ---
   2009  11   12.6     6.5       0   220.4     ---   
   2009  12    7.2     0.0      15   114.9     ---   
   2010   1    6.0    -1.2      16    73.5     ---   
   2010   2    7.3     0.8       7    72.1     ---  
EOF

echo "Testing your program with a text file containing:"
cat data1.txt
echo ""
echo "Output of your program:"
java \${prog1} data1.txt
 
EEOOFF
 
chmod +x vpl_execution


vpl_evaluate.sh


#! /bin/bash
# D. Thiebaut

cat > vpl_execution <<EEOOFF
#! /bin/bash
 
# --- program tested (no extension) ---
prog1=Hw3_2
gradeNotCompile=20
gradeCompileNoGoodOutput=30
gradeIncrement=35    # (100-30)/2 / number of tests

# --- 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

# =================================================
# --- create test input files ---
cat > data1.txt <<EOF
Cardiff Bute Park
Location 3176E 1773N, 9 metres amsl
Estimated data is marked with a * after the value.

   yyyy  mm   tmax    tmin      af    rain     sun
              degC    degC    days      mm   hours
   1977   9   18.3     8.1       0    48.6   117.9
   1977  10   15.4     9.0       0    76.0    80.4
   1977  11   10.3     4.7       4   147.9    76.4
   1977  12    9.6     4.6       2    88.0    25.6
   1978   1    7.5     2.0       6   134.1    64.7
   1978   2    6.2     0.9      13   134.1    56.9
...
   2009   7   20.2    13.1       0   194.1     ---
   2009   8   20.7     5.5       0    76.0     120.5
   2009   9   19.1    10.6       0    34.7     ---
   2009  10   16.3     8.6       0    73.6     ---
   2009  11   12.6     6.5       0   220.4     ---   
   2009  12    7.2     0.0      15   114.9     ---   
   2010   1    6.0    -1.2      16    73.5     ---   
   2010   2    7.3     0.8       7    72.1     ---  
EOF

cat > data2.txt <<EOF
   yyyy  mm   tmax    tmin      af    rain     sun
              degC    degC    days      mm   hours
   1976   9   18.3     8.1       0    30.3   117.9
   1979   9   18.3     8.1       0    48.6   ---
EOF
    
#--- create expected outputs ---
cat > data1.out <<EOF
rain 2009 220.40
sun 2009 120.50
EOF

cat > data2.out <<EOF
rain 1979 48.60
sun 1976 117.90
EOF

# =================================================
# function that prints the difference between user and expected output
incorrectOutput() {
    if [ "\$1" ]; then   # if there's a parameter
        i=\$1
        echo "Comment :=>>- Your output is incorrect."

        #--- display test file ---
        echo "Comment :=>>- Your program tested with:"
        echo "<|--" 
        cat data\${i}.txt
        echo "--|>"

        echo "Comment :=>> ---------------"
        echo "Comment :=>>- Your output:"
        echo "Comment :=>> ---------------"
        echo "<|--"
        cat user.out.org
        echo "--|>"
        echo ""
        echo "Comment :=>> ---------------"
        echo "Comment :=>>- Expected output (only the numbers): "
        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
}

# =================================================
# --- LOOP THROUGH THE TEST FILES ---

for i in 1 2  ; do
   echo "Comment :=>>-TEST \$i"

   # ==============================================
   # 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 ---

   #--- spawn the program and get its pid ---
   timeout 30 java \${prog1} data\${i}.txt  &> user.out
   retcode=\$?

   #--- if we killed the waiter, everything is good ---
   if [ \$retcode -eq  124 ]; then
       echo "Comment :=>>-Your program has stopped working."
       timeoutOutput \$i
       continue
   else
       echo "Comment :=>>-Your program ran to completion."
   fi

   cp user.out user.out.org

   #--- 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

# =================================================
# Report grade
if (( grade > 100 )); then
   grade=100
fi
echo "Grade :=>> \$grade"

EEOOFF
 
chmod +x vpl_execution