#! /usr/bin/perl
+# Find the directory that contains the grading files.
+our ($GRADES_DIR);
+
+# Add our Perl library directory to the include path.
+BEGIN {
+ ($GRADES_DIR = $0) =~ s#/[^/]+$##;
+ -d $GRADES_DIR or die "$GRADES_DIR: stat: $!\n";
+ unshift @INC, "$GRADES_DIR/../lib";
+}
+
use warnings;
use strict;
use POSIX;
my ($exitcode) = @_;
print "run-tests, for grading Pintos thread projects.\n\n";
print "Invoke from a directory containing a student tarball named by\n";
- print "the submit script, e.g. username.Oct.12.04.20.04.09.tar.gz.\n";
+ print "the submit script, e.g. username.MMM.DD.YY.hh.mm.ss.tar.gz.\n";
print "In normal usage, no options are needed.\n\n";
print "Output is produced in tests.out and details.out.\n\n";
print "Options:\n";
print OUT "$p_got points out of $p_pos total\n\n";
print OUT map ("$_\n", @tests), "\n";
- print OUT map ("$_\n", @review);
+ print OUT map ("$_\n", @review), "\n";
+
+ print OUT "DETAILS\n";
+ print OUT "-------\n\n";
+ print OUT map ("$_\n", snarf ("details.out"));
exit 0;
}
-# Find the directory that contains the grading files.
-our ($GRADES_DIR);
-($GRADES_DIR = $0) =~ s#/[^/]+$##;
--d $GRADES_DIR or die "$GRADES_DIR: stat: $!\n";
-
if ($clean) {
# Verify that we're roughly in the correct directory
# before we go blasting away files.
close (CONSTANTS);
}
+ # Changes devices/timer.c if necessary.
+ my ($new_time_slice) = $test eq 'priority-fifo' ? 100 : 1;
+ my (@timer) = snarf ("pintos/src/devices/timer.c");
+ if (!grep (/^\#define TIME_SLICE $new_time_slice$/, @timer)) {
+ @timer = grep (!/^\#define TIME_SLICE/, @timer);
+ unshift (@timer, "#define TIME_SLICE $new_time_slice");
+ open (TIMER, ">pintos/src/devices/timer.c");
+ print TIMER map ("$_\n", @timer);
+ close (TIMER);
+ }
+
# Copy in the new test.c and delete enough files to ensure a full rebuild.
my ($src) = test_source ($test);
xsystem ("cp $src pintos/src/threads/test.c", DIE => "cp failed\n");
}
# They differ. Output a diff.
- my ($diff) = "";
+ my (@diff) = "";
my ($d) = Algorithm::Diff->new (\@expected, \@actual);
- $d->Base (1);
while ($d->Next ()) {
my ($ef, $el, $af, $al) = $d->Get (qw (min1 max1 min2 max2));
if ($d->Same ()) {
- if ($af != $al) {
- $diff .= "Actual lines $af...$al match expected lines "
- . "$ef...$el.\n";
- } else {
- $diff .= "Actual line $af matches expected line $ef.\n";
- }
+ push (@diff, map (" $_", $d->Items (1)));
} else {
- my (@i1) = $d->Items (1);
- my (@i2) = $d->Items (2);
- if (!@i1) {
- $diff .= "Extra or misplaced line(s) $af...$al "
- . "in actual output:\n";
- $diff .= number_lines ($af, \@i2);
- } elsif (!$d->Items (2)) {
- $diff .= "Expected line(s) $ef...$el missing or misplaced:\n";
- $diff .= number_lines ($ef, \@i1);
- } else {
- $diff .= "The following expected line(s) $ef...$el:\n";
- $diff .= number_lines ($ef, \@i1);
- $diff .= "became actual line(s) $af...$al:\n";
- $diff .= number_lines ($af, \@i2);
- }
+ push (@diff, map ("- $_", $d->Items (1))) if $d->Items (1);
+ push (@diff, map ("+ $_", $d->Items (2))) if $d->Items (2);
}
}
my ($details) = "";
- $details .= "$test actual output (line numbers added):\n";
- $details .= number_lines (1, \@actual);
- $details .= "\n$test expected output (line numbers added):\n";
- $details .= number_lines (1, \@expected);
- $details .= "\n$diff\n";
+ $details .= "$test actual output:\n";
+ $details .= join ('', map (" $_", @actual));
+ $details .= "\n$test expected output:\n";
+ $details .= join ('', map (" $_", @expected));
+ $details .= "\nOutput differences in `diff -u' format:\n";
+ $details .= join ('', @diff) . "\n";
$details{$test} = $details;
die "Output differs from expected. Details at end of file.\n";
}
unlink ("output/$log.err") if defined ($log) && $status == 0;
+ die $options{DIE} if $status != 0 && defined $options{DIE};
+
return $status == 0;
}