+exit success () if $action eq 'test';
+
+assemble_final_grade ();
+exit if $action eq 'assemble';
+
+die "Don't know how to '$action'";
+
+# Runs $test in directory output/$test.
+# Returns 'ok' if it went ok, otherwise an explanation.
+sub run_test {
+ my ($result);
+
+ 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/$hw/build/os.dsk "
+ . "--fs-disk=output/$test/fs.dsk "
+ . "--swap-disk=output/$test/swap.dsk "
+ . "-v";
+ $result = run_pintos ("$pintos_base_cmd put -f $GRADES_DIR/$test $test",
+ LOG => "$test/put", TIMEOUT => 60);
+ return $result if $result 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) {
+ $result = run_pintos ("$pintos_base_cmd put $GRADES_DIR/$fn $fn",
+ LOG => "$test/put-$fn", TIMEOUT => 60);
+ return "Error running `put $fn': $result" if $result ne 'ok';
+ }
+
+ # Run.
+ return run_pintos ("$pintos_base_cmd run -q -ex \"$test\"",
+ LOG => "$test/run", TIMEOUT => 120);
+}