SRCDIR = ../../src
-SINGLETONS = \
+# Main test programs.
+TESTS = \
$(addprefix args-, argc argv0 argvn single multiple dbl-space) \
$(addprefix sc-, bad-sp bad-arg boundary) \
halt exit \
$(addprefix open-, normal missing boundary empty null bad-ptr twice) \
$(addprefix close-, normal twice stdin stdout bad-fd) \
$(addprefix read-, normal bad-ptr boundary zero stdout bad-fd) \
- $(addprefix write-, normal bad-ptr boundary zero stdin bad-fd)
+ $(addprefix write-, normal bad-ptr boundary zero stdin bad-fd) \
+ $(addprefix exec-, once arg multiple missing bad-ptr) \
+ $(addprefix join-, simple twice killed bad-pid)
-define SINGLETON_PROG
+define TEST_PROG
PROGS += $(1)
$(subst -,_,$(1))_SRC = $(1).c
endef
-$(foreach prog,$(SINGLETONS),$(eval $(call SINGLETON_PROG,$(prog))))
+$(foreach prog,$(TESTS),$(eval $(call TEST_PROG,$(prog))))
DISKS = $(patsubst %,%.dsk,$(PROGS))
disks: $(DISKS)
+# Other programs needed by some of the main test programs.
+PROGS += child-simple child-arg child-bad
+child_simple_SRC = child-simple.c
+child_arg_SRC = child-arg.c
+child_bad_SRC = child-bad.c
+exec-once.dsk exec-multiple.dsk join-simple.dsk join-twice.dsk: child-simple
+exec-arg.dsk: child-arg
+join-killed.dsk: child-bad
+
%.dsk: %
./prep-disk $<
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+
+int
+main (int argc, char *argv[])
+{
+ if (!strcmp (argv[0], "childarg") || !strcmp (argv[1], "childarg"))
+ {
+ printf ("(child-arg) success\n");
+ return 0;
+ }
+ else
+ {
+ int i;
+
+ printf ("(child-arg) failure\n");
+ printf ("(child-arg) argc=%d\n", argc);
+ for (i = 0; i <= argc; i++)
+ if (argv[i] >= (char *) 0xbffff000 && argv[i] < (char *) 0xc0000000)
+ printf ("(child-arg) argv[%d]='%s'\n", i, argv[i]);
+ else
+ printf ("(child-arg) argv[%d]=%p\n", i, argv[i]);
+ return 1;
+ }
+}
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ printf ("(child-bad) begin\n");
+ asm volatile ("mov $0xc0101234, %esp; int $0x30");
+ printf ("(child-bad) end\n");
+ return 0;
+}
--- /dev/null
+#include <stdio.h>
+
+int
+main (void)
+{
+ printf ("(child-simple) run\n");
+ return 81;
+}
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ printf ("(exec-arg) begin\n");
+ join (exec ("child-arg childarg"));
+ printf ("(exec-arg) end\n");
+ return 0;
+}
--- /dev/null
+(exec-arg) begin
+(child-arg) success
+child-arg: exit(0)
+(exec-arg) end
+exec-arg: exit(0)
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ printf ("(exec-bad-ptr) begin\n");
+ exec ((char *) 0xc0101234);
+ printf ("(exec-bad-ptr) end\n");
+ return 0;
+}
--- /dev/null
+(exec-bad-ptr) begin
+(exec-bad-ptr) end
+exec-bad-ptr: exit(0)
+--OR--
+(exec-bad-ptr) begin
+exec-bad-ptr: exit(-1)
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ printf ("(exec-missing) begin\n");
+ printf ("(exec-missing) exec(\"no-such-file\"): %d\n",
+ exec ("no-such-file"));
+ printf ("(exec-missing) end\n");
+ return 0;
+}
--- /dev/null
+(exec-missing) begin
+(exec-missing) exec("no-such-file"): -1
+(exec-missing) end
+exec-missing: exit(0)
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ printf ("(exec-multiple) begin\n");
+ join (exec ("child-simple"));
+ join (exec ("child-simple"));
+ join (exec ("child-simple"));
+ join (exec ("child-simple"));
+ printf ("(exec-multiple) end\n");
+ return 0;
+}
--- /dev/null
+(exec-multiple) begin
+(child-simple) run
+child-simple: exit(81)
+(child-simple) run
+child-simple: exit(81)
+(child-simple) run
+child-simple: exit(81)
+(child-simple) run
+child-simple: exit(81)
+(exec-multiple) end
+exec-multiple: exit(0)
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ printf ("(exec-once) begin\n");
+ join (exec ("child-simple"));
+ printf ("(exec-once) end\n");
+ return 0;
+}
--- /dev/null
+(exec-once) begin
+(child-simple) run
+child-simple: exit(81)
+(exec-once) end
+exec-once: exit(0)
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ printf ("(join-bad-pid) begin\n");
+ join ((pid_t) 0xc0101234);
+ printf ("(join-bad-pid) end\n");
+ return 0;
+}
--- /dev/null
+(join-simple) begin
+(join-simple) join(exec()) = 81
+(join-simple) end
+join-simple: exit(0)
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ printf ("(join-killed) begin\n");
+ printf ("(join-killed) join(exec()) = %d\n", join (exec ("child-bad")));
+ printf ("(join-killed) end\n");
+ return 0;
+}
--- /dev/null
+(join-killed) begin
+(child-bad) begin
+child-bad: exit(-1)
+(join-killed) join(exec()) = -1
+(join-killed) end
+join-killed: exit(0)
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ printf ("(join-simple) begin\n");
+ printf ("(join-simple) join(exec()) = %d\n", join (exec ("child-simple")));
+ printf ("(join-simple) end\n");
+ return 0;
+}
--- /dev/null
+(join-simple) begin
+(child-simple) run
+child-simple: exit(81)
+(join-simple) join(exec()) = 81
+(join-simple) end
+join-simple: exit(0)
--- /dev/null
+#include <stdio.h>
+#include <syscall.h>
+
+int
+main (void)
+{
+ pid_t child;
+ printf ("(join-twice) begin\n");
+ child = exec ("child-twice");
+ printf ("(join-twice) join(exec()) = %d\n", join (child));
+ join (child);
+ printf ("(join-twice) end\n");
+ return 0;
+}
--- /dev/null
+(join-twice) begin
+(child-twice) run
+child-twice: exit(81)
+(join-twice) join(exec()) = 81
+(join-twice) end
+join-twice: exit(0)
close-normal close-twice
read-normal read-bad-ptr read-boundary read-zero
write-normal write-bad-ptr write-boundary write-zero));
+put_file ("child-simple") if $test eq 'exec-once' or $test eq 'exec-multiple';
+put_file ("child-arg") if $test eq 'exec-arg';
sub put_file {
my ($fn) = @_;
read-bad-fd
write-normal write-bad-ptr write-boundary write-zero write-stdin
write-bad-fd
+ exec-once exec-arg exec-multiple exec-missing exec-bad-ptr
) unless @TESTS > 0;
our (%args);
compare_output ("$GRADES_DIR/write-normal.exp", @output);
my ($test_txt) = "output/$test/test.txt";
get_file ("test.txt", $test_txt) if ! -e $test_txt;
- compare_output ("$GRADES_DIR/sample.txt", snarf ($test_txt));
+
+ my (@actual) = snarf ($test_txt);
+ my (@expected) = snarf ("$GRADES_DIR/sample.txt");
+
+ my ($eq);
+ if ($#actual == $#expected) {
+ $eq = 1;
+ for my $i (0...$#actual) {
+ $eq = 0 if $actual[$i] ne $expected[$i];
+ }
+ } else {
+ $eq = 0;
+ }
+ if (!$eq) {
+ my ($details);
+ $details = "Expected file content:\n";
+ $details .= join ('', map (" $_\n", @expected));
+ $details .= "Actual file content:\n";
+ $details .= join ('', map (" $_\n", @actual));
+ $extra{$test} = $details;
+
+ die "File written didn't have expected content.\n";
+ }
}
sub get_file {
System calls: exec
-2 exec-once: call exec/join once
+ -2 exec-arg: check command-line passing on exec
-2 exec-multiple: call exec/join multiple times
-2 exec-missing: exec of nonexistent file must return -1
-1 exec-bad-ptr: pass invalid pointer to exec system call
-Score: /7
+Score: /9
System calls: join
-2 join-simple: join must return proper value