SRCDIR = ../../src
-SINGLETONS = create-normal create-empty create-null create-invalid create-long
+SINGLETONS = \
+ $(addprefix create-, normal empty null bad-ptr long exists bound) \
+ $(addprefix args-, argc argv0 argvn single multiple dbl-space)
define SINGLETON_PROG
PROGS += $(1)
rm -f $(DISKS)
include $(SRCDIR)/Makefile.userprog
+
+CFLAGS += -Werror
--- /dev/null
+#include <debug.h>
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (int argc, char *argv[] UNUSED)
+{
+ printf ("(args-argc) argc=%d\n", argc);
+ return 0;
+}
--- /dev/null
+(args-argc) argc=5
+args-argc: exit(0)
--- /dev/null
+#include <debug.h>
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (int argc UNUSED, char *argv[])
+{
+ printf ("(args-argv0) argv[0] = '%s'\n", argv[0]);
+ return 0;
+}
--- /dev/null
+(args-argv0) argv[0] = 'args-argv0'
+args-argv0: exit(0)
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (int argc, char *argv[])
+{
+ printf ("(args-argvn) argv[argc] = %p\n", argv[argc]);
+ return 0;
+}
--- /dev/null
+(args-argvn) argv[argc] = 0x0
+args-argvn: exit(0)
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+
+int
+main (int argc, char *argv[])
+{
+ int i;
+
+ for (i = 0; i < argc; i++)
+ {
+ int j;
+
+ for (j = i; j < i + 2; j++)
+ if (argv[j] == NULL)
+ goto error;
+ if (!strcmp (argv[i], "two")
+ && !strcmp (argv[i + 1], "args"))
+ {
+ printf ("(args-dbl-space) success\n");
+ return 0;
+ }
+ error:;
+ }
+
+ printf ("(args-dbl-space) failure\n");
+ printf ("(args-dbl-space) argc=%d\n", argc);
+ for (i = 0; i <= argc; i++)
+ if (argv[i] >= (char *) 0xbffff000 && argv[i] < (char *) 0xc0000000)
+ printf ("(args-dbl-space) argv[%d]='%s'\n", i, argv[i]);
+ else
+ printf ("(args-dbl-space) argv[%d]=%p\n", i, argv[i]);
+ return 1;
+}
--- /dev/null
+(args-dbl-space) success
+args-dbl-space: exit(0)
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+
+int
+main (int argc, char *argv[])
+{
+ int i;
+
+ for (i = 0; i < argc - 2; i++)
+ {
+ int j;
+
+ for (j = i; j < i + 4; j++)
+ if (argv[j] == NULL)
+ goto error;
+ if (!strcmp (argv[i], "some")
+ && !strcmp (argv[i + 1], "arguments")
+ && !strcmp (argv[i + 2], "for")
+ && !strcmp (argv[i + 3], "you!"))
+ {
+ printf ("(args-multiple) success\n");
+ return 0;
+ }
+ error:;
+ }
+
+ printf ("(args-multiple) failure\n");
+ printf ("(args-multiple) argc=%d\n", argc);
+ for (i = 0; i <= argc; i++)
+ if (argv[i] >= (char *) 0xbffff000 && argv[i] < (char *) 0xc0000000)
+ printf ("(args-multiple) argv[%d]='%s'\n", i, argv[i]);
+ else
+ printf ("(args-multiple) argv[%d]=%p\n", i, argv[i]);
+ return 1;
+}
--- /dev/null
+(args-multiple) success
+args-multiple: exit(0)
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+
+int
+main (int argc, char *argv[])
+{
+ if (!strcmp (argv[0], "onearg") || !strcmp (argv[1], "onearg"))
+ {
+ printf ("(args-single) success\n");
+ return 0;
+ }
+ else
+ {
+ int i;
+
+ printf ("(args-single) failure\n");
+ printf ("(args-single) argc=%d\n", argc);
+ for (i = 0; i <= argc; i++)
+ if (argv[i] >= (char *) 0xbffff000 && argv[i] < (char *) 0xc0000000)
+ printf ("(args-single) argv[%d]='%s'\n", i, argv[i]);
+ else
+ printf ("(args-single) argv[%d]=%p\n", i, argv[i]);
+ return 1;
+ }
+}
--- /dev/null
+(args-single) success
+args-single: exit(0)
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ printf ("(create-bad-ptr) begin\n");
+ create ((char *) 0xc0101234, 0);
+ printf ("(create-bad-ptr) end\n");
+ return 0;
+}
--- /dev/null
+(create-bad-ptr) begin
+(create-bad-ptr) end
+create-bad-ptr: exit(0)
+--OR--
+(create-bad-ptr) begin
+create-bad-ptr: exit(-1)
--- /dev/null
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <syscall.h>
+
+static char *
+mk_boundary_string (const char *src)
+{
+ static char dst[8192];
+ char *p = dst + (4096 - (uintptr_t) dst % 4096 - strlen (src) / 2);
+ strlcpy (p, src, 4096);
+ return p;
+}
+
+int
+main (void)
+{
+ printf ("(create-bound) begin\n");
+ printf ("(create-bound) create(): %d\n",
+ create (mk_boundary_string ("quux.dat"), 0));
+ printf ("(create-bound) end\n");
+ return 0;
+}
--- /dev/null
+(create-bound) begin
+(create-bound) create(): 1
+(create-bound) end
+create-bound: exit(0)
(create-empty) begin
(create-empty) end
create-empty: exit(0)
+--OR--
+(create-empty) begin
+create-empty: exit(-1)
+++ /dev/null
-(create-empty) begin
-create-empty: exit(-1)
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ printf ("(create-exists) begin\n");
+ printf ("(create-exists) create(\"quux.dat\"): %d\n",
+ create ("quux.dat", 0));
+ printf ("(create-exists) create(\"warble.dat\"): %d\n",
+ create ("warble.dat", 0));
+ printf ("(create-exists) create(\"quux.dat\"): %d\n",
+ create ("quux.dat", 0));
+ printf ("(create-exists) end\n");
+ return 0;
+}
--- /dev/null
+(create-exists) begin
+(create-exists) create("quux.dat"): 1
+(create-exists) create("warble.dat"): 1
+(create-exists) create("quux.dat"): 0
+(create-exists) end
+create-exists: exit(0)
+++ /dev/null
-#include <stdio.h>
-#include <syscall.h>
-
-int
-main (void)
-{
- printf ("create(0xc0101234):\n");
- printf ("%d\n", create ((char *) 0xc0101234, 0));
- printf ("survived\n");
- return 0;
-}
memset (name, 'x', sizeof name);
name[sizeof name - 1] = '\0';
- printf ("create(\"%s\"):\n", name);
- printf ("%d\n", create (name, 0));
- printf ("survived\n");
+ printf ("(create-long) begin\n");
+ printf ("(create-long) create: %d\n", create (name, 0));
+ printf ("(create-long) end\n");
return 0;
}
--- /dev/null
+(create-long) begin
+(create-long) create: 0
+(create-long) end
+create-long: exit(0)
(create-null) begin
(create-null) end
create-null: exit(0)
+--OR--
+(create-null) begin
+create-null: exit(-1)
+++ /dev/null
-(create-null) begin
-create-null: exit(-1)
}
# Default set of tests.
-@TESTS = qw (create-normal create-empty create-null
- create-long)
+@TESTS = qw (create-normal create-empty create-null create-bad-ptr
+ create-long create-exists create-bound
+ args-argc args-argv0 args-argvn args-single args-multiple
+ args-dbl-space)
unless @TESTS > 0;
+our (%args);
+for my $key ('args-argc', 'args-argv0', 'args-argvn', 'args-multiple') {
+ $args{$key} = "some arguments for you!";
+}
+$args{'args-single'} = "onearg";
+$args{'args-dbl-space'} = "two args";
+
# Handle final grade mode.
if ($grade) {
open (OUT, ">grade.out") or die "grade.out: create: $!\n";
# Run.
my ($timeout) = 10;
+ my ($testargs) = defined ($args{$test}) ? " $args{$test}" : "";
xsystem ("pintos "
. "--os-disk=pintos/src/userprog/build/os.dsk "
. "--fs-disk=output/$test/fs.dsk "
- . "-v run -q -ex \"$test\"",
+ . "-v run -q -ex \"$test$testargs\"",
LOG => "$test/run",
TIMEOUT => $timeout)
or return "Bochs error";
return "ok";
}
\f
-sub grade_create_empty {
- my (@output) = @_;
- verify_common (@_);
- compare_output (["(create-empty) begin"], @output);
-
-}
-
sub grade_alarm_multiple {
verify_alarm (7, @_);
}
if !grep (/Powering off/, @output);
}
-sub eq_lines {
- my ($actual, $expected) = @_;
- return $actual eq $expected;
-}
-
-sub compare_output {
- my ($exp, @actual) = @_;
- @actual = map ("$_\n", @actual);
+# Get @output without header or trailer.
+sub get_core_output {
+ my (@output) = @_;
- # Trim header and trailer from @actual.
our ($test);
my ($first);
- for ($first = 0; $first <= $#actual; $first++) {
- $first++, last if $actual[$first] =~ /^Executing '$test':$/;
+ for ($first = 0; $first <= $#output; $first++) {
+ $first++, last if $output[$first] =~ /^Executing '$test.*':$/;
}
my ($last);
- for ($last = $#actual; $last >= 0; $last--) {
- $last--, last if $actual[$last] =~ /^Timer: \d+ ticks$/;
+ for ($last = $#output; $last >= 0; $last--) {
+ $last--, last if $output[$last] =~ /^Timer: \d+ ticks$/;
}
if ($last < $first) {
- my ($no_first) = $first > $#actual;
- my ($no_last) = $last < $#actual;
+ my ($no_first) = $first > $#output;
+ my ($no_last) = $last < $#output;
die "Couldn't locate output.\n";
}
- @actual = @actual[$first ... $last];
+ return @output[$first ... $last];
+}
+
+sub compare_output {
+ my ($exp, @actual) = @_;
+ @actual = get_core_output (map ("$_\n", @actual));
# Fix up lines that look like exit codes.
for my $i (0...$#actual) {
if (my ($process, $code)
= $actual[$i] =~ /^([-a-zA-Z0-9 ]+):.*[ \(](-?\d+)\b\)?$/) {
$process = substr ($process, 0, 15);
+ $process =~ s/\s.*//;
$actual[$i] = "$process: exit($code)\n";
}
}
$details .= "$test actual output:\n";
$details .= join ('', map (" $_", @actual));
+ my (@exp) = map ("$_\n", snarf ($exp));
+
my ($fuzzy_match) = 0;
- for (my ($i) = 0; ; $i++) {
- my ($fn) = $exp;
- $fn .= $i if $i;
- if (! -e $fn) {
- die "$exp: stat: $!\n" if !$i;
- last;
+ while (@exp != 0) {
+ my (@expected);
+ while (@exp != 0) {
+ my ($s) = shift (@exp);
+ last if $s eq "--OR--\n";
+ push (@expected, $s);
}
- my (@expected) = map ("$_\n", snarf ($fn));
$details .= "\n$test acceptable output:\n";
$details .= join ('', map (" $_", @expected));
if ($#actual == $#expected) {
my ($eq) = 1;
for (my ($i) = 0; $i <= $#expected; $i++) {
- $eq = 0 if !eq_lines ($actual[$i], $expected[$i]);
+ $eq = 0 if $actual[$i] ne $expected[$i];
}
return if $eq;
}
Argument passing
-3 args-argc: argc is not set correctly
-3 args-argv0: executable name not passed as argv[0]
+ -3 args-argvn: argv[argc] is not a null pointer
+ -3 args-single: passing single argument fails
-3 args-multiple: passing multiple arguments fails
- -3 args-dblspace: using multiple spaces between arguments fails
-Score: /12
+ -3 args-dbl-space: using multiple spaces between arguments fails
+Score: /18
System calls
- -3 syscall-bad-sp: system call with a bad stack pointer must not crash OS
- -3 syscall-bad-arg: syscall with argument off top of stack must not crash OS
- -3 syscall-boundary: syscall with args across page boundary must work
+ -3 sc-bad-sp: system call with a bad stack pointer must not crash OS
+ -3 sc-bad-arg: syscall with argument off top of stack must not crash OS
+ -3 sc-boundary: syscall with args across page boundary must work
Score: /9
System calls: halt, exec
-1 create-bad-ptr: pass invalid pointer to create system call
-1 create-long: pass long file name to create system call
-1 create-exists: pass name of an existing file to create system call
- -1 create-boundary: pass name of file crossing page boundary
+ -1 create-bound: pass name of file crossing page boundary
Score: /7
System calls: open