X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=grading%2Flib%2FPintos%2FGrading.pm;h=d48b2751c92219f4a1b55f3771d0e2a9cc657cd0;hb=fbea5921d53e698fee2014995cdb13ddb67a982f;hp=200b779ebbcbe853ff9d09893fe399c7a6e9c098;hpb=d5b6f0eba392ee44f68cda2a821eac8fffa683e2;p=pintos-anon diff --git a/grading/lib/Pintos/Grading.pm b/grading/lib/Pintos/Grading.pm index 200b779..d48b275 100644 --- a/grading/lib/Pintos/Grading.pm +++ b/grading/lib/Pintos/Grading.pm @@ -5,43 +5,87 @@ our ($test); our ($GRADES_DIR); our ($verbose); -our (%args); our %result; our %details; our %extra; our @TESTS; -our $clean; -our $grade; +our $action; our $hw; use POSIX; -use Getopt::Long; +use Getopt::Long qw(:config no_ignore_case); use Algorithm::Diff; sub parse_cmd_line { + my ($do_regex, $no_regex); GetOptions ("v|verbose+" => \$verbose, "h|help" => sub { usage (0) }, - "t|test=s" => \@TESTS, - "c|clean" => \$clean, - "g|grade" => \$grade) + "d|do-tests=s" => \$do_regex, + "n|no-tests=s" => \$no_regex, + "c|clean" => sub { set_action ('clean'); }, + "x|extract" => sub { set_action ('extract'); }, + "b|build" => sub { set_action ('build'); }, + "t|test" => sub { set_action ('test'); }, + "a|assemble" => sub { set_action ('assemble'); }) or die "Malformed command line; use --help for help.\n"; - die "Non-option argument not supported; use --help for help.\n" + die "Non-option arguments not supported; use --help for help.\n" if @ARGV > 0; + @TESTS = split(/,/, join (',', @TESTS)) if defined @TESTS; + + if (!defined $action) { + $action = -e 'review.txt' ? 'assemble' : 'test'; + } + + my (@default_tests) = @_; + @TESTS = @default_tests; + @TESTS = grep (/$do_regex/, @TESTS) if defined $do_regex; + @TESTS = grep (!/$no_regex/, @TESTS) if defined $no_regex; +} + +sub set_action { + my ($new_action) = @_; + die "actions `$action' and `$new_action' conflict\n" + if defined ($action) && $action ne $new_action; + $action = $new_action; } sub usage { my ($exitcode) = @_; - print "run-tests, for grading Pintos projects.\n\n"; - print "Invoke from a directory containing a student tarball named by\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 " -c, --clean Remove old output files before starting\n"; - print " -t, --test=TEST Execute TEST only (allowed multiple times)\n"; - print " -g, --grade Instead of running tests, compose grade.out\n"; - print " -v, --verbose Print commands before executing them\n"; - print " -h, --help Print this help message\n"; + print < "make") - or return "compile error"; + xsystem ("cd pintos/src/$hw && make", LOG => "make") eq 'ok' + or return "Build error"; } # Run and grade the tests. @@ -137,17 +184,17 @@ sub run_and_grade_tests { for $test (@TESTS) { print "$test: "; my ($result) = get_test_result (); - if ($result eq 'ok') { - $result = grade_test ($test); - } elsif ($result =~ /^Timed out/) { - $result = "$result - " . grade_test ($test); - } chomp ($result); - print "$result"; - print " - with warnings" if $result eq 'ok' && defined $details{$test}; - print "\n"; + + my ($grade) = grade_test ($test); + chomp ($grade); - $result{$test} = $result; + my ($msg) = $result eq 'ok' ? $grade : "$result - $grade"; + $msg .= " - with warnings" + if $grade eq 'ok' && defined $details{$test}; + print "$msg\n"; + + $result{$test} = $grade; } } @@ -330,9 +377,16 @@ sub get_test_result { rename "output/$test", "output/$test.old" or die "rename: $!\n" if -d "output/$test"; + # Make output directory. + mkdir "output/$test"; + # Run the test. my ($result) = run_test ($test); + # Delete any disks in the output directory because they take up + # lots of space. + unlink (glob ("output/$test/*.dsk")); + # Save the results for later. open (DONE, ">$cache_file") or die "$cache_file: create: $!\n"; print DONE "$result\n"; @@ -341,59 +395,14 @@ sub get_test_result { return $result; } -# Creates an output directory for the test, -# creates all the files needed -sub run_test { - # Make output directory. - mkdir "output/$test"; - - my ($fs_size) = $test ne 'grow-too-big' ? 2 : .25; - xsystem ("pintos make-disk output/$test/fs.dsk $fs_size >/dev/null 2>&1", - DIE => "failed to create file system disk"); - xsystem ("pintos make-disk output/$test/swap.dsk 2 >/dev/null 2>&1", - DIE => "failed to create swap disk"); - - # Format disk, install test. - my ($pintos_base_cmd) = - "pintos " - . "--os-disk=pintos/src/filesys/build/os.dsk " - . "--fs-disk=output/$test/fs.dsk " - . "--swap-disk=output/$test/swap.dsk " - . "-v"; - unlink ("output/$test/fs.dsk", "output/$test/swap.dsk"), - return "format/put error" - if xsystem ("$pintos_base_cmd put -f $GRADES_DIR/$test $test", - LOG => "$test/put", TIMEOUT => 60, EXPECT => 1) ne 'ok'; - - my (@extra_files); - push (@extra_files, "child-syn-read") if $test eq 'syn-read'; - push (@extra_files, "child-syn-wrt") if $test eq 'syn-write'; - push (@extra_files, "child-syn-rw") if $test eq 'syn-rw'; - for my $fn (@extra_files) { - return "format/put error" - if xsystem ("$pintos_base_cmd put $GRADES_DIR/$fn $fn", - LOG => "$test/put-$fn", TIMEOUT => 60, EXPECT => 1) - ne 'ok'; - } - - # Run. - my ($timeout) = 120; - my ($testargs) = defined ($args{$test}) ? " $args{$test}" : ""; - my ($retval) = - xsystem ("$pintos_base_cmd run -q -ex \"$test$testargs\"", - LOG => "$test/run", TIMEOUT => $timeout, EXPECT => 1); - my ($result); - if ($retval eq 'ok') { - $result = "ok"; - } elsif ($retval eq 'timeout') { - $result = "Timed out after $timeout seconds"; - } elsif ($retval eq 'error') { - $result = "Bochs error"; - } else { - die; - } - unlink ("output/$test/fs.dsk", "output/$test/swap.dsk"); - return $result; +sub run_pintos { + my ($cmd_line, %args) = @_; + $args{EXPECT} = 1 unless defined $args{EXPECT}; + my ($retval) = xsystem ($cmd_line, %args); + return 'ok' if $retval eq 'ok'; + return "Timed out after $args{TIMEOUT} seconds" if $retval eq 'timeout'; + return 'Error running Bochs' if $retval eq 'error'; + die; } # Grade the test. @@ -433,7 +442,7 @@ sub grade_test { # Do final grade. # Combines grade.txt, tests.out, review.txt, and details.out, # producing grade.out. -sub compose_final_grade { +sub assemble_final_grade { open (OUT, ">grade.out") or die "grade.out: create: $!\n"; open (GRADE, "); @@ -611,7 +626,12 @@ sub get_core_output { my ($first); for ($first = 0; $first <= $#output; $first++) { - $first++, last if $output[$first] =~ /^Executing '$test.*':$/; + my ($line) = $output[$first]; + $first++, last + if ($hw ne 'threads' && $line =~ /^Executing '$test.*':$/) + || ($hw eq 'threads' + && grep (/^Boot complete.$/, @output[0...$first - 1]) + && $line =~ /^\s*$/); } my ($last);