aboutsummaryrefslogtreecommitdiff
path: root/autograder
diff options
context:
space:
mode:
Diffstat (limited to 'autograder')
-rwxr-xr-xautograder/sdriver.pl210
-rw-r--r--autograder/trace01.txt5
-rw-r--r--autograder/trace02.txt5
-rw-r--r--autograder/trace03.txt5
-rw-r--r--autograder/trace04.txt5
-rw-r--r--autograder/trace05.txt11
-rw-r--r--autograder/trace06.txt8
-rw-r--r--autograder/trace07.txt14
-rw-r--r--autograder/trace08.txt14
-rw-r--r--autograder/trace09.txt20
-rw-r--r--autograder/trace10.txt22
-rw-r--r--autograder/trace11.txt12
-rw-r--r--autograder/trace12.txt17
-rw-r--r--autograder/trace13.txt23
-rw-r--r--autograder/trace14.txt47
-rw-r--r--autograder/trace15.txt46
-rw-r--r--autograder/trace16.txt16
17 files changed, 480 insertions, 0 deletions
diff --git a/autograder/sdriver.pl b/autograder/sdriver.pl
new file mode 100755
index 0000000..852bf3d
--- /dev/null
+++ b/autograder/sdriver.pl
@@ -0,0 +1,210 @@
+#!/usr/bin/perl
+#!/usr/local/bin/perl
+use Getopt::Std;
+use FileHandle;
+use IPC::Open2;
+
+#######################################################################
+# sdriver.pl - Shell driver
+#
+# Copyright (c) 2002, R. Bryant and D. O'Hallaron, All rights reserved.
+# May not be used, modified, or copied without permission.
+#
+# The driver runs a student's shell program as a child, sends
+# commands and signals to the child as directed by a trace file,
+# and captures and displays the output produced by the child.
+#
+# Tracefile format:
+#
+# The tracefile consists of text lines that are either blank lines,
+# comment lines, driver commands, or shell commands. Blank lines are
+# ignored. Comment lines begin with "#" and are echo'd without change
+# to stdout. Driver commands are intepreted by the driver and are not
+# passed to the child shell. All other lines are shell commands and
+# are passed without modification to the shell, which reads them on
+# stdin. Output produced by the child on stdout/stderr is read by
+# the parent and printed on its stdout.
+#
+# Driver commands:
+# TSTP Send a SIGTSTP signal to the child
+# INT Send a SIGINT signal to the child
+# QUIT Send a SIGQUIT signal to the child
+# KILL Send a SIGKILL signal to the child
+# CLOSE Close Writer (sends EOF signal to child)
+# WAIT Wait() for child to terminate
+# SLEEP <n> Sleep for <n> seconds
+#
+######################################################################
+
+#
+# usage - print help message and terminate
+#
+sub usage
+{
+ printf STDERR "$_[0]\n";
+ printf STDERR "Usage: $0 [-hv] -t <trace> -s <shellprog> -a <args>\n";
+ printf STDERR "Options:\n";
+ printf STDERR " -h Print this message\n";
+ printf STDERR " -v Be more verbose\n";
+ printf STDERR " -t <trace> Trace file\n";
+ printf STDERR " -s <shell> Shell program to test\n";
+ printf STDERR " -a <args> Shell arguments\n";
+ printf STDERR " -g Generate output for autograder\n";
+ die "\n" ;
+}
+
+# Parse the command line arguments
+getopts('hgvt:s:a:');
+if ($opt_h) {
+ usage();
+}
+if (!$opt_t) {
+ usage("Missing required -t argument");
+}
+if (!$opt_s) {
+ usage("Missing required -s argument");
+}
+$verbose = $opt_v;
+$infile = $opt_t;
+$shellprog = $opt_s;
+$shellargs = $opt_a;
+$grade = $opt_g;
+
+# Make sure the input script exists and is readable
+-e $infile
+ or die "$0: ERROR: $infile not found\n";
+-r $infile
+ or die "$0: ERROR: $infile is not readable\n";
+
+# Make sure the shell program exists and is executable
+-e $shellprog
+ or die "$0: ERROR: $shellprog not found\n";
+-x $shellprog
+ or die "$0: ERROR: $shellprog is not executable\n";
+
+
+# Open the input script
+open INFILE, $infile
+ or die "$0: ERROR: Couldn't open input file $infile: $!\n";
+
+#
+# Fork a child, run the shell in it, and connect the parent
+# and child with a pair of unidirectional pipes:
+# parent:Writer -> child:stdin
+# child:stdout -> parent:Reader
+#
+$pid = open2(\*Reader, \*Writer, "$shellprog $shellargs");
+Writer->autoflush();
+
+# The autograder will want to know the child shell's pid
+if ($grade) {
+ print ("pid=$pid\n");
+}
+
+#
+# Parent reads a trace file, sends commands to the child shell.
+#
+while (<INFILE>) {
+ $line = $_;
+ chomp($line);
+
+ # Comment line
+ if ($line =~ /^#/) {
+ print "$line\n";
+ }
+
+ # Blank line
+ elsif ($line =~ /^\s*$/) {
+ if ($verbose) {
+ print "$0: Ignoring blank line\n";
+ }
+ }
+
+ # Send SIGTSTP (ctrl-z)
+ elsif ($line =~ /TSTP/) {
+ if ($verbose) {
+ print "$0: Sending SIGTSTP signal to process $pid\n";
+ }
+ kill 'TSTP', $pid;
+ }
+
+ # Send SIGINT (ctrl-c)
+ elsif ($line =~ /INT/) {
+ if ($verbose) {
+ print "$0: Sending SIGINT signal to process $pid\n";
+ }
+ kill 'INT', $pid;
+ }
+
+ # Send SIGQUIT (whenever we need graceful termination)
+ elsif ($line =~ /QUIT/) {
+ if ($verbose) {
+ print "$0: Sending SIGQUIT signal to process $pid\n";
+ }
+ kill 'QUIT', $pid;
+ }
+
+ # Send SIGKILL
+ elsif ($line =~ /KILL/) {
+ if ($verbose) {
+ print "$0: Sending SIGKILL signal to process $pid\n";
+ }
+ kill 'KILL', $pid;
+ }
+
+ # Close pipe (sends EOF notification to child)
+ elsif ($line =~ /CLOSE/) {
+ if ($verbose) {
+ print "$0: Closing output end of pipe to child $pid\n";
+ }
+ close Writer;
+ }
+
+ # Wait for child to terminate
+ elsif ($line =~ /WAIT/) {
+ if ($verbose) {
+ print "$0: Waiting for child $pid\n";
+ }
+ wait;
+ if ($verbose) {
+ print "$0: Child $pid reaped\n";
+ }
+ }
+
+ # Sleep
+ elsif ($line =~ /SLEEP (\d+)/) {
+ if ($verbose) {
+ print "$0: Sleeping $1 secs\n";
+ }
+ sleep $1;
+ }
+
+ # Unknown input
+ else {
+ if ($verbose) {
+ print "$0: Sending :$line: to child $pid\n";
+ }
+ print Writer "$line\n";
+ }
+}
+
+#
+# Parent echoes the output produced by the child.
+#
+close Writer;
+if ($verbose) {
+ print "$0: Reading data from child $pid\n";
+}
+while ($line = <Reader>) {
+ print $line;
+}
+close Reader;
+
+# Finally, parent reaps child
+wait;
+
+if ($verbose) {
+ print "$0: Shell terminated\n";
+}
+
+exit;
diff --git a/autograder/trace01.txt b/autograder/trace01.txt
new file mode 100644
index 0000000..9c8561e
--- /dev/null
+++ b/autograder/trace01.txt
@@ -0,0 +1,5 @@
+#
+# trace01.txt - Properly terminate on EOF.
+#
+CLOSE
+WAIT
diff --git a/autograder/trace02.txt b/autograder/trace02.txt
new file mode 100644
index 0000000..e97643b
--- /dev/null
+++ b/autograder/trace02.txt
@@ -0,0 +1,5 @@
+#
+# trace02.txt - Process builtin quit command.
+#
+quit
+WAIT
diff --git a/autograder/trace03.txt b/autograder/trace03.txt
new file mode 100644
index 0000000..be8869c
--- /dev/null
+++ b/autograder/trace03.txt
@@ -0,0 +1,5 @@
+#
+# trace03.txt - Run a foreground job.
+#
+/bin/echo tsh> quit
+quit
diff --git a/autograder/trace04.txt b/autograder/trace04.txt
new file mode 100644
index 0000000..554df0e
--- /dev/null
+++ b/autograder/trace04.txt
@@ -0,0 +1,5 @@
+#
+# trace04.txt - Run a background job.
+#
+/bin/echo -e tsh> ./myspin 1 \046
+./myspin 1 &
diff --git a/autograder/trace05.txt b/autograder/trace05.txt
new file mode 100644
index 0000000..03c1876
--- /dev/null
+++ b/autograder/trace05.txt
@@ -0,0 +1,11 @@
+#
+# trace05.txt - Process jobs builtin command.
+#
+/bin/echo -e tsh> ./myspin 2 \046
+./myspin 2 &
+
+/bin/echo -e tsh> ./myspin 3 \046
+./myspin 3 &
+
+/bin/echo tsh> jobs
+jobs
diff --git a/autograder/trace06.txt b/autograder/trace06.txt
new file mode 100644
index 0000000..bfa3890
--- /dev/null
+++ b/autograder/trace06.txt
@@ -0,0 +1,8 @@
+#
+# trace06.txt - Forward SIGINT to foreground job.
+#
+/bin/echo -e tsh> ./myspin 4
+./myspin 4
+
+SLEEP 2
+INT
diff --git a/autograder/trace07.txt b/autograder/trace07.txt
new file mode 100644
index 0000000..259a285
--- /dev/null
+++ b/autograder/trace07.txt
@@ -0,0 +1,14 @@
+#
+# trace07.txt - Forward SIGINT only to foreground job.
+#
+/bin/echo -e tsh> ./myspin 4 \046
+./myspin 4 &
+
+/bin/echo -e tsh> ./myspin 5
+./myspin 5
+
+SLEEP 2
+INT
+
+/bin/echo tsh> jobs
+jobs
diff --git a/autograder/trace08.txt b/autograder/trace08.txt
new file mode 100644
index 0000000..49be19f
--- /dev/null
+++ b/autograder/trace08.txt
@@ -0,0 +1,14 @@
+#
+# trace08.txt - Forward SIGTSTP only to foreground job.
+#
+/bin/echo -e tsh> ./myspin 4 \046
+./myspin 4 &
+
+/bin/echo -e tsh> ./myspin 5
+./myspin 5
+
+SLEEP 2
+TSTP
+
+/bin/echo tsh> jobs
+jobs
diff --git a/autograder/trace09.txt b/autograder/trace09.txt
new file mode 100644
index 0000000..340d998
--- /dev/null
+++ b/autograder/trace09.txt
@@ -0,0 +1,20 @@
+#
+# trace09.txt - Process bg builtin command
+#
+/bin/echo -e tsh> ./myspin 4 \046
+./myspin 4 &
+
+/bin/echo -e tsh> ./myspin 5
+./myspin 5
+
+SLEEP 2
+TSTP
+
+/bin/echo tsh> jobs
+jobs
+
+/bin/echo tsh> bg %2
+bg %2
+
+/bin/echo tsh> jobs
+jobs
diff --git a/autograder/trace10.txt b/autograder/trace10.txt
new file mode 100644
index 0000000..e7de996
--- /dev/null
+++ b/autograder/trace10.txt
@@ -0,0 +1,22 @@
+#
+# trace10.txt - Process fg builtin command.
+#
+/bin/echo -e tsh> ./myspin 4 \046
+./myspin 4 &
+
+SLEEP 1
+/bin/echo tsh> fg %1
+fg %1
+
+SLEEP 1
+TSTP
+
+/bin/echo tsh> jobs
+jobs
+
+/bin/echo tsh> fg %1
+fg %1
+
+/bin/echo tsh> jobs
+jobs
+
diff --git a/autograder/trace11.txt b/autograder/trace11.txt
new file mode 100644
index 0000000..d2f8663
--- /dev/null
+++ b/autograder/trace11.txt
@@ -0,0 +1,12 @@
+#
+# trace11.txt - Forward SIGINT to every process in foreground process group
+#
+/bin/echo -e tsh> ./mysplit 4
+./mysplit 4
+
+SLEEP 2
+INT
+
+/bin/echo tsh> /bin/ps a
+/bin/ps a
+
diff --git a/autograder/trace12.txt b/autograder/trace12.txt
new file mode 100644
index 0000000..88455e3
--- /dev/null
+++ b/autograder/trace12.txt
@@ -0,0 +1,17 @@
+#
+# trace12.txt - Forward SIGTSTP to every process in foreground process group
+#
+/bin/echo -e tsh> ./mysplit 4
+./mysplit 4
+
+SLEEP 2
+TSTP
+
+/bin/echo tsh> jobs
+jobs
+
+/bin/echo tsh> /bin/ps a
+/bin/ps a
+
+
+
diff --git a/autograder/trace13.txt b/autograder/trace13.txt
new file mode 100644
index 0000000..d734cbc
--- /dev/null
+++ b/autograder/trace13.txt
@@ -0,0 +1,23 @@
+#
+# trace13.txt - Restart every stopped process in process group
+#
+/bin/echo -e tsh> ./mysplit 4
+./mysplit 4
+
+SLEEP 2
+TSTP
+
+/bin/echo tsh> jobs
+jobs
+
+/bin/echo tsh> /bin/ps a
+/bin/ps a
+
+/bin/echo tsh> fg %1
+fg %1
+
+/bin/echo tsh> /bin/ps a
+/bin/ps a
+
+
+
diff --git a/autograder/trace14.txt b/autograder/trace14.txt
new file mode 100644
index 0000000..8086580
--- /dev/null
+++ b/autograder/trace14.txt
@@ -0,0 +1,47 @@
+#
+# trace14.txt - Simple error handling
+#
+/bin/echo tsh> ./bogus
+./bogus
+
+/bin/echo -e tsh> ./myspin 4 \046
+./myspin 4 &
+
+/bin/echo tsh> fg
+fg
+
+/bin/echo tsh> bg
+bg
+
+/bin/echo tsh> fg a
+fg a
+
+/bin/echo tsh> bg a
+bg a
+
+/bin/echo tsh> fg 9999999
+fg 9999999
+
+/bin/echo tsh> bg 9999999
+bg 9999999
+
+/bin/echo tsh> fg %2
+fg %2
+
+/bin/echo tsh> fg %1
+fg %1
+
+SLEEP 2
+TSTP
+
+/bin/echo tsh> bg %2
+bg %2
+
+/bin/echo tsh> bg %1
+bg %1
+
+/bin/echo tsh> jobs
+jobs
+
+
+
diff --git a/autograder/trace15.txt b/autograder/trace15.txt
new file mode 100644
index 0000000..2cc780e
--- /dev/null
+++ b/autograder/trace15.txt
@@ -0,0 +1,46 @@
+#
+# trace15.txt - Putting it all together
+#
+
+/bin/echo tsh> ./bogus
+./bogus
+
+/bin/echo tsh> ./myspin 10
+./myspin 10
+
+SLEEP 2
+INT
+
+/bin/echo -e tsh> ./myspin 3 \046
+./myspin 3 &
+
+/bin/echo -e tsh> ./myspin 4 \046
+./myspin 4 &
+
+/bin/echo tsh> jobs
+jobs
+
+/bin/echo tsh> fg %1
+fg %1
+
+SLEEP 2
+TSTP
+
+/bin/echo tsh> jobs
+jobs
+
+/bin/echo tsh> bg %3
+bg %3
+
+/bin/echo tsh> bg %1
+bg %1
+
+/bin/echo tsh> jobs
+jobs
+
+/bin/echo tsh> fg %1
+fg %1
+
+/bin/echo tsh> quit
+quit
+
diff --git a/autograder/trace16.txt b/autograder/trace16.txt
new file mode 100644
index 0000000..822ba14
--- /dev/null
+++ b/autograder/trace16.txt
@@ -0,0 +1,16 @@
+#
+# trace16.txt - Tests whether the shell can handle SIGTSTP and SIGINT
+# signals that come from other processes instead of the terminal.
+#
+
+/bin/echo tsh> ./mystop 2
+./mystop 2
+
+SLEEP 3
+
+/bin/echo tsh> jobs
+jobs
+
+/bin/echo tsh> ./myint 2
+./myint 2
+