From e7bc50ca8ffcaa6ed68ebd2315f78b0f5a7d10ad Mon Sep 17 00:00:00 2001 From: klaar36 Date: Fri, 20 Mar 2015 17:30:24 +0100 Subject: Initial Pintos --- src/tests/userprog/Grading | 11 ++ src/tests/userprog/Make.tests | 125 ++++++++++++++++++++++ src/tests/userprog/Make.tests.odig | 132 +++++++++++++++++++++++ src/tests/userprog/Rubric.functionality | 52 ++++++++++ src/tests/userprog/Rubric.robustness | 48 +++++++++ src/tests/userprog/args-dbl-space.ck | 15 +++ src/tests/userprog/args-many.ck | 35 +++++++ src/tests/userprog/args-multiple.ck | 17 +++ src/tests/userprog/args-none.ck | 13 +++ src/tests/userprog/args-single.ck | 14 +++ src/tests/userprog/args.c | 25 +++++ src/tests/userprog/bad-jump.c | 13 +++ src/tests/userprog/bad-jump.ck | 9 ++ src/tests/userprog/bad-jump2.c | 13 +++ src/tests/userprog/bad-jump2.ck | 9 ++ src/tests/userprog/bad-read.c | 13 +++ src/tests/userprog/bad-read.ck | 9 ++ src/tests/userprog/bad-read2.c | 13 +++ src/tests/userprog/bad-read2.ck | 9 ++ src/tests/userprog/bad-write.c | 12 +++ src/tests/userprog/bad-write.ck | 9 ++ src/tests/userprog/bad-write2.c | 12 +++ src/tests/userprog/bad-write2.ck | 9 ++ src/tests/userprog/boundary.c | 33 ++++++ src/tests/userprog/boundary.h | 7 ++ src/tests/userprog/child-bad.c | 14 +++ src/tests/userprog/child-close.c | 28 +++++ src/tests/userprog/child-rox.c | 55 ++++++++++ src/tests/userprog/child-simple.c | 15 +++ src/tests/userprog/close-bad-fd.c | 11 ++ src/tests/userprog/close-bad-fd.ck | 13 +++ src/tests/userprog/close-normal.c | 14 +++ src/tests/userprog/close-normal.ck | 12 +++ src/tests/userprog/close-stdin.c | 11 ++ src/tests/userprog/close-stdin.ck | 13 +++ src/tests/userprog/close-stdout.c | 11 ++ src/tests/userprog/close-stdout.ck | 13 +++ src/tests/userprog/close-twice.c | 18 ++++ src/tests/userprog/close-twice.ck | 19 ++++ src/tests/userprog/create-bad-ptr.c | 12 +++ src/tests/userprog/create-bad-ptr.ck | 9 ++ src/tests/userprog/create-bound.c | 14 +++ src/tests/userprog/create-bound.ck | 11 ++ src/tests/userprog/create-empty.c | 10 ++ src/tests/userprog/create-empty.ck | 14 +++ src/tests/userprog/create-exists.c | 16 +++ src/tests/userprog/create-exists.ck | 15 +++ src/tests/userprog/create-long.c | 17 +++ src/tests/userprog/create-long.ck | 11 ++ src/tests/userprog/create-normal.c | 10 ++ src/tests/userprog/create-normal.ck | 11 ++ src/tests/userprog/create-null.c | 11 ++ src/tests/userprog/create-null.ck | 9 ++ src/tests/userprog/exec-arg.c | 10 ++ src/tests/userprog/exec-arg.ck | 17 +++ src/tests/userprog/exec-bad-ptr.c | 11 ++ src/tests/userprog/exec-bad-ptr.ck | 13 +++ src/tests/userprog/exec-missing.c | 12 +++ src/tests/userprog/exec-missing.ck | 31 ++++++ src/tests/userprog/exec-multiple.c | 14 +++ src/tests/userprog/exec-multiple.ck | 18 ++++ src/tests/userprog/exec-once.c | 11 ++ src/tests/userprog/exec-once.ck | 12 +++ src/tests/userprog/exit.c | 11 ++ src/tests/userprog/exit.ck | 9 ++ src/tests/userprog/halt.c | 11 ++ src/tests/userprog/halt.ck | 15 +++ src/tests/userprog/lib/.cvsignore | 1 + src/tests/userprog/lib/user/.cvsignore | 1 + src/tests/userprog/lib/user/.dummy | 0 src/tests/userprog/multi-child-fd.c | 25 +++++ src/tests/userprog/multi-child-fd.ck | 25 +++++ src/tests/userprog/multi-recurse.c | 34 ++++++ src/tests/userprog/multi-recurse.ck | 70 +++++++++++++ src/tests/userprog/no-vm/Make.tests | 8 ++ src/tests/userprog/no-vm/Rubric | 3 + src/tests/userprog/no-vm/multi-oom.c | 179 ++++++++++++++++++++++++++++++++ src/tests/userprog/no-vm/multi-oom.ck | 10 ++ src/tests/userprog/null.ck | 8 ++ src/tests/userprog/open-bad-ptr.c | 13 +++ src/tests/userprog/open-bad-ptr.ck | 13 +++ src/tests/userprog/open-boundary.c | 14 +++ src/tests/userprog/open-boundary.ck | 11 ++ src/tests/userprog/open-empty.c | 13 +++ src/tests/userprog/open-empty.ck | 10 ++ src/tests/userprog/open-missing.c | 13 +++ src/tests/userprog/open-missing.ck | 10 ++ src/tests/userprog/open-normal.c | 13 +++ src/tests/userprog/open-normal.ck | 10 ++ src/tests/userprog/open-null.c | 12 +++ src/tests/userprog/open-null.ck | 13 +++ src/tests/userprog/open-twice.c | 19 ++++ src/tests/userprog/open-twice.ck | 12 +++ src/tests/userprog/read-bad-fd.c | 21 ++++ src/tests/userprog/read-bad-fd.ck | 13 +++ src/tests/userprog/read-bad-ptr.c | 16 +++ src/tests/userprog/read-bad-ptr.ck | 15 +++ src/tests/userprog/read-boundary.c | 30 ++++++ src/tests/userprog/read-boundary.ck | 11 ++ src/tests/userprog/read-normal.c | 11 ++ src/tests/userprog/read-normal.ck | 13 +++ src/tests/userprog/read-stdout.c | 14 +++ src/tests/userprog/read-stdout.ck | 13 +++ src/tests/userprog/read-zero.c | 22 ++++ src/tests/userprog/read-zero.ck | 11 ++ src/tests/userprog/rox-child.c | 5 + src/tests/userprog/rox-child.ck | 20 ++++ src/tests/userprog/rox-child.inc | 33 ++++++ src/tests/userprog/rox-multichild.c | 5 + src/tests/userprog/rox-multichild.ck | 44 ++++++++ src/tests/userprog/rox-simple.c | 19 ++++ src/tests/userprog/rox-simple.ck | 13 +++ src/tests/userprog/sample.inc | 6 ++ src/tests/userprog/sample.txt | 4 + src/tests/userprog/sc-bad-arg.c | 17 +++ src/tests/userprog/sc-bad-arg.ck | 9 ++ src/tests/userprog/sc-bad-sp.c | 20 ++++ src/tests/userprog/sc-bad-sp.ck | 9 ++ src/tests/userprog/sc-boundary-2.c | 22 ++++ src/tests/userprog/sc-boundary-2.ck | 9 ++ src/tests/userprog/sc-boundary.c | 22 ++++ src/tests/userprog/sc-boundary.ck | 9 ++ src/tests/userprog/wait-bad-pid.c | 11 ++ src/tests/userprog/wait-bad-pid.ck | 13 +++ src/tests/userprog/wait-killed.c | 11 ++ src/tests/userprog/wait-killed.ck | 13 +++ src/tests/userprog/wait-simple.c | 11 ++ src/tests/userprog/wait-simple.ck | 13 +++ src/tests/userprog/wait-twice.c | 15 +++ src/tests/userprog/wait-twice.ck | 14 +++ src/tests/userprog/write-bad-fd.c | 20 ++++ src/tests/userprog/write-bad-fd.ck | 13 +++ src/tests/userprog/write-bad-ptr.c | 16 +++ src/tests/userprog/write-bad-ptr.ck | 15 +++ src/tests/userprog/write-boundary.c | 25 +++++ src/tests/userprog/write-boundary.ck | 11 ++ src/tests/userprog/write-normal.c | 20 ++++ src/tests/userprog/write-normal.ck | 12 +++ src/tests/userprog/write-stdin.c | 14 +++ src/tests/userprog/write-stdin.ck | 13 +++ src/tests/userprog/write-zero.c | 20 ++++ src/tests/userprog/write-zero.ck | 11 ++ 142 files changed, 2556 insertions(+) create mode 100644 src/tests/userprog/Grading create mode 100644 src/tests/userprog/Make.tests create mode 100644 src/tests/userprog/Make.tests.odig create mode 100644 src/tests/userprog/Rubric.functionality create mode 100644 src/tests/userprog/Rubric.robustness create mode 100644 src/tests/userprog/args-dbl-space.ck create mode 100644 src/tests/userprog/args-many.ck create mode 100644 src/tests/userprog/args-multiple.ck create mode 100644 src/tests/userprog/args-none.ck create mode 100644 src/tests/userprog/args-single.ck create mode 100644 src/tests/userprog/args.c create mode 100644 src/tests/userprog/bad-jump.c create mode 100644 src/tests/userprog/bad-jump.ck create mode 100644 src/tests/userprog/bad-jump2.c create mode 100644 src/tests/userprog/bad-jump2.ck create mode 100644 src/tests/userprog/bad-read.c create mode 100644 src/tests/userprog/bad-read.ck create mode 100644 src/tests/userprog/bad-read2.c create mode 100644 src/tests/userprog/bad-read2.ck create mode 100644 src/tests/userprog/bad-write.c create mode 100644 src/tests/userprog/bad-write.ck create mode 100644 src/tests/userprog/bad-write2.c create mode 100644 src/tests/userprog/bad-write2.ck create mode 100644 src/tests/userprog/boundary.c create mode 100644 src/tests/userprog/boundary.h create mode 100644 src/tests/userprog/child-bad.c create mode 100644 src/tests/userprog/child-close.c create mode 100644 src/tests/userprog/child-rox.c create mode 100644 src/tests/userprog/child-simple.c create mode 100644 src/tests/userprog/close-bad-fd.c create mode 100644 src/tests/userprog/close-bad-fd.ck create mode 100644 src/tests/userprog/close-normal.c create mode 100644 src/tests/userprog/close-normal.ck create mode 100644 src/tests/userprog/close-stdin.c create mode 100644 src/tests/userprog/close-stdin.ck create mode 100644 src/tests/userprog/close-stdout.c create mode 100644 src/tests/userprog/close-stdout.ck create mode 100644 src/tests/userprog/close-twice.c create mode 100644 src/tests/userprog/close-twice.ck create mode 100644 src/tests/userprog/create-bad-ptr.c create mode 100644 src/tests/userprog/create-bad-ptr.ck create mode 100644 src/tests/userprog/create-bound.c create mode 100644 src/tests/userprog/create-bound.ck create mode 100644 src/tests/userprog/create-empty.c create mode 100644 src/tests/userprog/create-empty.ck create mode 100644 src/tests/userprog/create-exists.c create mode 100644 src/tests/userprog/create-exists.ck create mode 100644 src/tests/userprog/create-long.c create mode 100644 src/tests/userprog/create-long.ck create mode 100644 src/tests/userprog/create-normal.c create mode 100644 src/tests/userprog/create-normal.ck create mode 100644 src/tests/userprog/create-null.c create mode 100644 src/tests/userprog/create-null.ck create mode 100644 src/tests/userprog/exec-arg.c create mode 100644 src/tests/userprog/exec-arg.ck create mode 100644 src/tests/userprog/exec-bad-ptr.c create mode 100644 src/tests/userprog/exec-bad-ptr.ck create mode 100644 src/tests/userprog/exec-missing.c create mode 100644 src/tests/userprog/exec-missing.ck create mode 100644 src/tests/userprog/exec-multiple.c create mode 100644 src/tests/userprog/exec-multiple.ck create mode 100644 src/tests/userprog/exec-once.c create mode 100644 src/tests/userprog/exec-once.ck create mode 100644 src/tests/userprog/exit.c create mode 100644 src/tests/userprog/exit.ck create mode 100644 src/tests/userprog/halt.c create mode 100644 src/tests/userprog/halt.ck create mode 100644 src/tests/userprog/lib/.cvsignore create mode 100644 src/tests/userprog/lib/user/.cvsignore create mode 100644 src/tests/userprog/lib/user/.dummy create mode 100644 src/tests/userprog/multi-child-fd.c create mode 100644 src/tests/userprog/multi-child-fd.ck create mode 100644 src/tests/userprog/multi-recurse.c create mode 100644 src/tests/userprog/multi-recurse.ck create mode 100644 src/tests/userprog/no-vm/Make.tests create mode 100644 src/tests/userprog/no-vm/Rubric create mode 100644 src/tests/userprog/no-vm/multi-oom.c create mode 100644 src/tests/userprog/no-vm/multi-oom.ck create mode 100644 src/tests/userprog/null.ck create mode 100644 src/tests/userprog/open-bad-ptr.c create mode 100644 src/tests/userprog/open-bad-ptr.ck create mode 100644 src/tests/userprog/open-boundary.c create mode 100644 src/tests/userprog/open-boundary.ck create mode 100644 src/tests/userprog/open-empty.c create mode 100644 src/tests/userprog/open-empty.ck create mode 100644 src/tests/userprog/open-missing.c create mode 100644 src/tests/userprog/open-missing.ck create mode 100644 src/tests/userprog/open-normal.c create mode 100644 src/tests/userprog/open-normal.ck create mode 100644 src/tests/userprog/open-null.c create mode 100644 src/tests/userprog/open-null.ck create mode 100644 src/tests/userprog/open-twice.c create mode 100644 src/tests/userprog/open-twice.ck create mode 100644 src/tests/userprog/read-bad-fd.c create mode 100644 src/tests/userprog/read-bad-fd.ck create mode 100644 src/tests/userprog/read-bad-ptr.c create mode 100644 src/tests/userprog/read-bad-ptr.ck create mode 100644 src/tests/userprog/read-boundary.c create mode 100644 src/tests/userprog/read-boundary.ck create mode 100644 src/tests/userprog/read-normal.c create mode 100644 src/tests/userprog/read-normal.ck create mode 100644 src/tests/userprog/read-stdout.c create mode 100644 src/tests/userprog/read-stdout.ck create mode 100644 src/tests/userprog/read-zero.c create mode 100644 src/tests/userprog/read-zero.ck create mode 100644 src/tests/userprog/rox-child.c create mode 100644 src/tests/userprog/rox-child.ck create mode 100644 src/tests/userprog/rox-child.inc create mode 100644 src/tests/userprog/rox-multichild.c create mode 100644 src/tests/userprog/rox-multichild.ck create mode 100644 src/tests/userprog/rox-simple.c create mode 100644 src/tests/userprog/rox-simple.ck create mode 100644 src/tests/userprog/sample.inc create mode 100644 src/tests/userprog/sample.txt create mode 100644 src/tests/userprog/sc-bad-arg.c create mode 100644 src/tests/userprog/sc-bad-arg.ck create mode 100644 src/tests/userprog/sc-bad-sp.c create mode 100644 src/tests/userprog/sc-bad-sp.ck create mode 100644 src/tests/userprog/sc-boundary-2.c create mode 100644 src/tests/userprog/sc-boundary-2.ck create mode 100644 src/tests/userprog/sc-boundary.c create mode 100644 src/tests/userprog/sc-boundary.ck create mode 100644 src/tests/userprog/wait-bad-pid.c create mode 100644 src/tests/userprog/wait-bad-pid.ck create mode 100644 src/tests/userprog/wait-killed.c create mode 100644 src/tests/userprog/wait-killed.ck create mode 100644 src/tests/userprog/wait-simple.c create mode 100644 src/tests/userprog/wait-simple.ck create mode 100644 src/tests/userprog/wait-twice.c create mode 100644 src/tests/userprog/wait-twice.ck create mode 100644 src/tests/userprog/write-bad-fd.c create mode 100644 src/tests/userprog/write-bad-fd.ck create mode 100644 src/tests/userprog/write-bad-ptr.c create mode 100644 src/tests/userprog/write-bad-ptr.ck create mode 100644 src/tests/userprog/write-boundary.c create mode 100644 src/tests/userprog/write-boundary.ck create mode 100644 src/tests/userprog/write-normal.c create mode 100644 src/tests/userprog/write-normal.ck create mode 100644 src/tests/userprog/write-stdin.c create mode 100644 src/tests/userprog/write-stdin.ck create mode 100644 src/tests/userprog/write-zero.c create mode 100644 src/tests/userprog/write-zero.ck (limited to 'src/tests/userprog') diff --git a/src/tests/userprog/Grading b/src/tests/userprog/Grading new file mode 100644 index 0000000..f70dc99 --- /dev/null +++ b/src/tests/userprog/Grading @@ -0,0 +1,11 @@ +# Percentage of the testing point total designated for each set of +# tests. + +# This project is primarily about implementing system calls. +# If you do so properly, the base file system functionality +# should come "for free". Thus, the points emphasis below. + +35% tests/userprog/Rubric.functionality +25% tests/userprog/Rubric.robustness +10% tests/userprog/no-vm/Rubric +30% tests/filesys/base/Rubric diff --git a/src/tests/userprog/Make.tests b/src/tests/userprog/Make.tests new file mode 100644 index 0000000..1258582 --- /dev/null +++ b/src/tests/userprog/Make.tests @@ -0,0 +1,125 @@ +# -*- makefile -*- + +tests/%.output: FSDISK = 2 +tests/%.output: PUTFILES = $(filter-out os.dsk, $^) + +tests/userprog_TESTS = $(addprefix tests/userprog/,args-none \ +args-single args-multiple args-many args-dbl-space sc-bad-sp \ +sc-bad-arg sc-boundary sc-boundary-2 halt exit create-normal \ +create-empty create-null create-bad-ptr create-long create-exists \ +create-bound open-normal open-missing open-boundary open-empty \ +open-null open-bad-ptr open-twice close-normal close-twice close-stdin \ +close-stdout close-bad-fd read-normal read-bad-ptr read-boundary \ +read-zero read-stdout 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 wait-simple wait-twice \ +wait-killed wait-bad-pid multi-recurse multi-child-fd) + + + +tests/userprog_PROGS = $(tests/userprog_TESTS) $(addprefix \ +tests/userprog/,child-simple child-args child-bad child-close) + + +tests/userprog/args-none_SRC = tests/userprog/args.c +tests/userprog/args-single_SRC = tests/userprog/args.c +tests/userprog/args-multiple_SRC = tests/userprog/args.c +tests/userprog/args-many_SRC = tests/userprog/args.c +tests/userprog/args-dbl-space_SRC = tests/userprog/args.c +tests/userprog/sc-bad-sp_SRC = tests/userprog/sc-bad-sp.c tests/main.c +tests/userprog/sc-bad-arg_SRC = tests/userprog/sc-bad-arg.c tests/main.c + +tests/userprog/sc-boundary_SRC = tests/userprog/sc-boundary.c \ +tests/userprog/boundary.c tests/main.c +tests/userprog/sc-boundary-2_SRC = tests/userprog/sc-boundary-2.c \ +tests/userprog/boundary.c tests/main.c +tests/userprog/halt_SRC = tests/userprog/halt.c tests/main.c +tests/userprog/exit_SRC = tests/userprog/exit.c tests/main.c +tests/userprog/create-normal_SRC = tests/userprog/create-normal.c tests/main.c +tests/userprog/create-empty_SRC = tests/userprog/create-empty.c tests/main.c +tests/userprog/create-null_SRC = tests/userprog/create-null.c tests/main.c +tests/userprog/create-bad-ptr_SRC = tests/userprog/create-bad-ptr.c \ +tests/main.c +tests/userprog/create-long_SRC = tests/userprog/create-long.c tests/main.c +tests/userprog/create-exists_SRC = tests/userprog/create-exists.c tests/main.c +tests/userprog/create-bound_SRC = tests/userprog/create-bound.c \ +tests/userprog/boundary.c tests/main.c +tests/userprog/open-normal_SRC = tests/userprog/open-normal.c tests/main.c +tests/userprog/open-missing_SRC = tests/userprog/open-missing.c tests/main.c +tests/userprog/open-boundary_SRC = tests/userprog/open-boundary.c \ +tests/userprog/boundary.c tests/main.c +tests/userprog/open-empty_SRC = tests/userprog/open-empty.c tests/main.c +tests/userprog/open-null_SRC = tests/userprog/open-null.c tests/main.c +tests/userprog/open-bad-ptr_SRC = tests/userprog/open-bad-ptr.c tests/main.c +tests/userprog/open-twice_SRC = tests/userprog/open-twice.c tests/main.c +tests/userprog/close-normal_SRC = tests/userprog/close-normal.c tests/main.c +tests/userprog/close-twice_SRC = tests/userprog/close-twice.c tests/main.c +tests/userprog/close-stdin_SRC = tests/userprog/close-stdin.c tests/main.c +tests/userprog/close-stdout_SRC = tests/userprog/close-stdout.c tests/main.c +tests/userprog/close-bad-fd_SRC = tests/userprog/close-bad-fd.c tests/main.c +tests/userprog/read-normal_SRC = tests/userprog/read-normal.c tests/main.c +tests/userprog/read-bad-ptr_SRC = tests/userprog/read-bad-ptr.c tests/main.c +tests/userprog/read-boundary_SRC = tests/userprog/read-boundary.c \ +tests/userprog/boundary.c tests/main.c +tests/userprog/read-zero_SRC = tests/userprog/read-zero.c tests/main.c +tests/userprog/read-stdout_SRC = tests/userprog/read-stdout.c tests/main.c +tests/userprog/read-bad-fd_SRC = tests/userprog/read-bad-fd.c tests/main.c +tests/userprog/write-normal_SRC = tests/userprog/write-normal.c tests/main.c +tests/userprog/write-bad-ptr_SRC = tests/userprog/write-bad-ptr.c tests/main.c +tests/userprog/write-boundary_SRC = tests/userprog/write-boundary.c \ +tests/userprog/boundary.c tests/main.c +tests/userprog/write-zero_SRC = tests/userprog/write-zero.c tests/main.c +tests/userprog/write-stdin_SRC = tests/userprog/write-stdin.c tests/main.c +tests/userprog/write-bad-fd_SRC = tests/userprog/write-bad-fd.c tests/main.c +tests/userprog/exec-once_SRC = tests/userprog/exec-once.c tests/main.c +tests/userprog/exec-arg_SRC = tests/userprog/exec-arg.c tests/main.c +tests/userprog/exec-multiple_SRC = tests/userprog/exec-multiple.c tests/main.c +tests/userprog/exec-missing_SRC = tests/userprog/exec-missing.c tests/main.c +tests/userprog/exec-bad-ptr_SRC = tests/userprog/exec-bad-ptr.c tests/main.c +tests/userprog/wait-simple_SRC = tests/userprog/wait-simple.c tests/main.c +tests/userprog/wait-twice_SRC = tests/userprog/wait-twice.c tests/main.c +tests/userprog/wait-killed_SRC = tests/userprog/wait-killed.c tests/main.c +tests/userprog/wait-bad-pid_SRC = tests/userprog/wait-bad-pid.c tests/main.c +tests/userprog/multi-recurse_SRC = tests/userprog/multi-recurse.c +tests/userprog/multi-child-fd_SRC = tests/userprog/multi-child-fd.c \ +tests/main.c + + +tests/userprog/child-simple_SRC = tests/userprog/child-simple.c +tests/userprog/child-args_SRC = tests/userprog/args.c +tests/userprog/child-bad_SRC = tests/userprog/child-bad.c tests/main.c +tests/userprog/child-close_SRC = tests/userprog/child-close.c + + +$(foreach prog,$(tests/userprog_PROGS),$(eval $(prog)_SRC += tests/lib.c)) + +tests/userprog/args-single_ARGS = onearg +tests/userprog/args-multiple_ARGS = some arguments for you! +tests/userprog/args-many_ARGS = a b c d e f g h i j k l m n o p q r s t u v +tests/userprog/args-dbl-space_ARGS = two spaces! +tests/userprog/multi-recurse_ARGS = 15 + +tests/userprog/open-normal_PUTFILES += tests/userprog/sample.txt +tests/userprog/open-boundary_PUTFILES += tests/userprog/sample.txt +tests/userprog/open-twice_PUTFILES += tests/userprog/sample.txt +tests/userprog/close-normal_PUTFILES += tests/userprog/sample.txt +tests/userprog/close-twice_PUTFILES += tests/userprog/sample.txt +tests/userprog/read-normal_PUTFILES += tests/userprog/sample.txt +tests/userprog/read-bad-ptr_PUTFILES += tests/userprog/sample.txt +tests/userprog/read-boundary_PUTFILES += tests/userprog/sample.txt +tests/userprog/read-zero_PUTFILES += tests/userprog/sample.txt +tests/userprog/write-normal_PUTFILES += tests/userprog/sample.txt +tests/userprog/write-bad-ptr_PUTFILES += tests/userprog/sample.txt +tests/userprog/write-boundary_PUTFILES += tests/userprog/sample.txt +tests/userprog/write-zero_PUTFILES += tests/userprog/sample.txt +tests/userprog/multi-child-fd_PUTFILES += tests/userprog/sample.txt + +tests/userprog/exec-once_PUTFILES += tests/userprog/child-simple +tests/userprog/exec-multiple_PUTFILES += tests/userprog/child-simple +tests/userprog/wait-simple_PUTFILES += tests/userprog/child-simple +tests/userprog/wait-twice_PUTFILES += tests/userprog/child-simple + +tests/userprog/exec-arg_PUTFILES += tests/userprog/child-args +tests/userprog/multi-child-fd_PUTFILES += tests/userprog/child-close +tests/userprog/wait-killed_PUTFILES += tests/userprog/child-bad + diff --git a/src/tests/userprog/Make.tests.odig b/src/tests/userprog/Make.tests.odig new file mode 100644 index 0000000..c762af3 --- /dev/null +++ b/src/tests/userprog/Make.tests.odig @@ -0,0 +1,132 @@ +# -*- makefile -*- + +tests/%.output: FSDISK = 2 +tests/%.output: PUTFILES = $(filter-out os.dsk, $^) + +tests/userprog_TESTS = $(addprefix tests/userprog/,args-none \ +args-single args-multiple args-many args-dbl-space sc-bad-sp \ +sc-bad-arg sc-boundary sc-boundary-2 halt exit create-normal \ +create-empty create-null create-bad-ptr create-long create-exists \ +create-bound open-normal open-missing open-boundary open-empty \ +open-null open-bad-ptr open-twice close-normal close-stdin \ +close-stdout close-bad-fd read-bad-ptr read-boundary \ +read-zero read-stdout 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 wait-simple wait-twice \ +wait-killed wait-bad-pid multi-recurse \ +) + +tests/userprog_PROGS = $(tests/userprog_TESTS) $(addprefix \ +tests/userprog/,child-simple child-args child-bad child-close child-rox) + +tests/userprog/args-none_SRC = tests/userprog/args.c +tests/userprog/args-single_SRC = tests/userprog/args.c +tests/userprog/args-multiple_SRC = tests/userprog/args.c +tests/userprog/args-many_SRC = tests/userprog/args.c +tests/userprog/args-dbl-space_SRC = tests/userprog/args.c +tests/userprog/sc-bad-sp_SRC = tests/userprog/sc-bad-sp.c tests/main.c +tests/userprog/sc-bad-arg_SRC = tests/userprog/sc-bad-arg.c tests/main.c +tests/userprog/bad-read_SRC = tests/userprog/bad-read.c tests/main.c +tests/userprog/bad-write_SRC = tests/userprog/bad-write.c tests/main.c +tests/userprog/bad-jump_SRC = tests/userprog/bad-jump.c tests/main.c +tests/userprog/bad-read2_SRC = tests/userprog/bad-read2.c tests/main.c +tests/userprog/bad-write2_SRC = tests/userprog/bad-write2.c tests/main.c +tests/userprog/bad-jump2_SRC = tests/userprog/bad-jump2.c tests/main.c +tests/userprog/sc-boundary_SRC = tests/userprog/sc-boundary.c \ +tests/userprog/boundary.c tests/main.c +tests/userprog/sc-boundary-2_SRC = tests/userprog/sc-boundary-2.c \ +tests/userprog/boundary.c tests/main.c +tests/userprog/halt_SRC = tests/userprog/halt.c tests/main.c +tests/userprog/exit_SRC = tests/userprog/exit.c tests/main.c +tests/userprog/create-normal_SRC = tests/userprog/create-normal.c tests/main.c +tests/userprog/create-empty_SRC = tests/userprog/create-empty.c tests/main.c +tests/userprog/create-null_SRC = tests/userprog/create-null.c tests/main.c +tests/userprog/create-bad-ptr_SRC = tests/userprog/create-bad-ptr.c \ +tests/main.c +tests/userprog/create-long_SRC = tests/userprog/create-long.c tests/main.c +tests/userprog/create-exists_SRC = tests/userprog/create-exists.c tests/main.c +tests/userprog/create-bound_SRC = tests/userprog/create-bound.c \ +tests/userprog/boundary.c tests/main.c +tests/userprog/open-normal_SRC = tests/userprog/open-normal.c tests/main.c +tests/userprog/open-missing_SRC = tests/userprog/open-missing.c tests/main.c +tests/userprog/open-boundary_SRC = tests/userprog/open-boundary.c \ +tests/userprog/boundary.c tests/main.c +tests/userprog/open-empty_SRC = tests/userprog/open-empty.c tests/main.c +tests/userprog/open-null_SRC = tests/userprog/open-null.c tests/main.c +tests/userprog/open-bad-ptr_SRC = tests/userprog/open-bad-ptr.c tests/main.c +tests/userprog/open-twice_SRC = tests/userprog/open-twice.c tests/main.c +tests/userprog/close-normal_SRC = tests/userprog/close-normal.c tests/main.c +tests/userprog/close-twice_SRC = tests/userprog/close-twice.c tests/main.c +tests/userprog/close-stdin_SRC = tests/userprog/close-stdin.c tests/main.c +tests/userprog/close-stdout_SRC = tests/userprog/close-stdout.c tests/main.c +tests/userprog/close-bad-fd_SRC = tests/userprog/close-bad-fd.c tests/main.c +tests/userprog/read-normal_SRC = tests/userprog/read-normal.c tests/main.c +tests/userprog/read-bad-ptr_SRC = tests/userprog/read-bad-ptr.c tests/main.c +tests/userprog/read-boundary_SRC = tests/userprog/read-boundary.c \ +tests/userprog/boundary.c tests/main.c +tests/userprog/read-zero_SRC = tests/userprog/read-zero.c tests/main.c +tests/userprog/read-stdout_SRC = tests/userprog/read-stdout.c tests/main.c +tests/userprog/read-bad-fd_SRC = tests/userprog/read-bad-fd.c tests/main.c +tests/userprog/write-normal_SRC = tests/userprog/write-normal.c tests/main.c +tests/userprog/write-bad-ptr_SRC = tests/userprog/write-bad-ptr.c tests/main.c +tests/userprog/write-boundary_SRC = tests/userprog/write-boundary.c \ +tests/userprog/boundary.c tests/main.c +tests/userprog/write-zero_SRC = tests/userprog/write-zero.c tests/main.c +tests/userprog/write-stdin_SRC = tests/userprog/write-stdin.c tests/main.c +tests/userprog/write-bad-fd_SRC = tests/userprog/write-bad-fd.c tests/main.c +tests/userprog/exec-once_SRC = tests/userprog/exec-once.c tests/main.c +tests/userprog/exec-arg_SRC = tests/userprog/exec-arg.c tests/main.c +tests/userprog/exec-multiple_SRC = tests/userprog/exec-multiple.c tests/main.c +tests/userprog/exec-missing_SRC = tests/userprog/exec-missing.c tests/main.c +tests/userprog/exec-bad-ptr_SRC = tests/userprog/exec-bad-ptr.c tests/main.c +tests/userprog/wait-simple_SRC = tests/userprog/wait-simple.c tests/main.c +tests/userprog/wait-twice_SRC = tests/userprog/wait-twice.c tests/main.c +tests/userprog/wait-killed_SRC = tests/userprog/wait-killed.c tests/main.c +tests/userprog/wait-bad-pid_SRC = tests/userprog/wait-bad-pid.c tests/main.c +tests/userprog/multi-recurse_SRC = tests/userprog/multi-recurse.c +tests/userprog/multi-child-fd_SRC = tests/userprog/multi-child-fd.c \ +tests/main.c +tests/userprog/rox-simple_SRC = tests/userprog/rox-simple.c tests/main.c +tests/userprog/rox-child_SRC = tests/userprog/rox-child.c tests/main.c +tests/userprog/rox-multichild_SRC = tests/userprog/rox-multichild.c \ +tests/main.c + +tests/userprog/child-simple_SRC = tests/userprog/child-simple.c +tests/userprog/child-args_SRC = tests/userprog/args.c +tests/userprog/child-bad_SRC = tests/userprog/child-bad.c tests/main.c +tests/userprog/child-close_SRC = tests/userprog/child-close.c +tests/userprog/child-rox_SRC = tests/userprog/child-rox.c + +$(foreach prog,$(tests/userprog_PROGS),$(eval $(prog)_SRC += tests/lib.c)) + +tests/userprog/args-single_ARGS = onearg +tests/userprog/args-multiple_ARGS = some arguments for you! +tests/userprog/args-many_ARGS = a b c d e f g h i j k l m n o p q r s t u v +tests/userprog/args-dbl-space_ARGS = two spaces! +tests/userprog/multi-recurse_ARGS = 15 + +tests/userprog/open-normal_PUTFILES += tests/userprog/sample.txt +tests/userprog/open-boundary_PUTFILES += tests/userprog/sample.txt +tests/userprog/open-twice_PUTFILES += tests/userprog/sample.txt +tests/userprog/close-normal_PUTFILES += tests/userprog/sample.txt +tests/userprog/close-twice_PUTFILES += tests/userprog/sample.txt +tests/userprog/read-normal_PUTFILES += tests/userprog/sample.txt +tests/userprog/read-bad-ptr_PUTFILES += tests/userprog/sample.txt +tests/userprog/read-boundary_PUTFILES += tests/userprog/sample.txt +tests/userprog/read-zero_PUTFILES += tests/userprog/sample.txt +tests/userprog/write-normal_PUTFILES += tests/userprog/sample.txt +tests/userprog/write-bad-ptr_PUTFILES += tests/userprog/sample.txt +tests/userprog/write-boundary_PUTFILES += tests/userprog/sample.txt +tests/userprog/write-zero_PUTFILES += tests/userprog/sample.txt +tests/userprog/multi-child-fd_PUTFILES += tests/userprog/sample.txt + +tests/userprog/exec-once_PUTFILES += tests/userprog/child-simple +tests/userprog/exec-multiple_PUTFILES += tests/userprog/child-simple +tests/userprog/wait-simple_PUTFILES += tests/userprog/child-simple +tests/userprog/wait-twice_PUTFILES += tests/userprog/child-simple + +tests/userprog/exec-arg_PUTFILES += tests/userprog/child-args +tests/userprog/multi-child-fd_PUTFILES += tests/userprog/child-close +tests/userprog/wait-killed_PUTFILES += tests/userprog/child-bad +tests/userprog/rox-child_PUTFILES += tests/userprog/child-rox +tests/userprog/rox-multichild_PUTFILES += tests/userprog/child-rox diff --git a/src/tests/userprog/Rubric.functionality b/src/tests/userprog/Rubric.functionality new file mode 100644 index 0000000..ea76c44 --- /dev/null +++ b/src/tests/userprog/Rubric.functionality @@ -0,0 +1,52 @@ +Functionality of system calls: +- Test argument passing on Pintos command line. +3 args-none +3 args-single +3 args-multiple +3 args-many +3 args-dbl-space + +- Test "create" system call. +3 create-empty +3 create-long +3 create-normal +3 create-exists + +- Test "open" system call. +3 open-missing +3 open-normal +3 open-twice + +- Test "read" system call. +3 read-normal +3 read-zero + +- Test "write" system call. +3 write-normal +3 write-zero + +- Test "close" system call. +3 close-normal + +- Test "exec" system call. +5 exec-once +5 exec-multiple +5 exec-arg + +- Test "wait" system call. +5 wait-simple +5 wait-twice + +- Test "exit" system call. +5 exit + +- Test "halt" system call. +3 halt + +- Test recursive execution of user programs. +15 multi-recurse + +- Test read-only executable feature. +3 rox-simple +3 rox-child +3 rox-multichild diff --git a/src/tests/userprog/Rubric.robustness b/src/tests/userprog/Rubric.robustness new file mode 100644 index 0000000..b7d1035 --- /dev/null +++ b/src/tests/userprog/Rubric.robustness @@ -0,0 +1,48 @@ +Robustness of system calls: +- Test robustness of file descriptor handling. +2 close-stdin +2 close-stdout +2 close-bad-fd +2 close-twice +2 read-bad-fd +2 read-stdout +2 write-bad-fd +2 write-stdin +2 multi-child-fd + +- Test robustness of pointer handling. +3 create-bad-ptr +3 exec-bad-ptr +3 open-bad-ptr +3 read-bad-ptr +3 write-bad-ptr + +- Test robustness of buffer copying across page boundaries. +3 create-bound +3 open-boundary +3 read-boundary +3 write-boundary + +- Test handling of null pointer and empty strings. +2 create-null +2 open-null +2 open-empty + +- Test robustness of system call implementation. +3 sc-bad-arg +3 sc-bad-sp +5 sc-boundary +5 sc-boundary-2 + +- Test robustness of "exec" and "wait" system calls. +5 exec-missing +5 wait-bad-pid +5 wait-killed + +- Test robustness of exception handling. +1 bad-read +1 bad-write +1 bad-jump +1 bad-read2 +1 bad-write2 +1 bad-jump2 diff --git a/src/tests/userprog/args-dbl-space.ck b/src/tests/userprog/args-dbl-space.ck new file mode 100644 index 0000000..dfbcf4b --- /dev/null +++ b/src/tests/userprog/args-dbl-space.ck @@ -0,0 +1,15 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(args) begin +(args) argc = 3 +(args) argv[0] = 'args-dbl-space' +(args) argv[1] = 'two' +(args) argv[2] = 'spaces!' +(args) argv[3] = null +(args) end +args-dbl-space: exit(0) +EOF +pass; diff --git a/src/tests/userprog/args-many.ck b/src/tests/userprog/args-many.ck new file mode 100644 index 0000000..214574a --- /dev/null +++ b/src/tests/userprog/args-many.ck @@ -0,0 +1,35 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(args) begin +(args) argc = 23 +(args) argv[0] = 'args-many' +(args) argv[1] = 'a' +(args) argv[2] = 'b' +(args) argv[3] = 'c' +(args) argv[4] = 'd' +(args) argv[5] = 'e' +(args) argv[6] = 'f' +(args) argv[7] = 'g' +(args) argv[8] = 'h' +(args) argv[9] = 'i' +(args) argv[10] = 'j' +(args) argv[11] = 'k' +(args) argv[12] = 'l' +(args) argv[13] = 'm' +(args) argv[14] = 'n' +(args) argv[15] = 'o' +(args) argv[16] = 'p' +(args) argv[17] = 'q' +(args) argv[18] = 'r' +(args) argv[19] = 's' +(args) argv[20] = 't' +(args) argv[21] = 'u' +(args) argv[22] = 'v' +(args) argv[23] = null +(args) end +args-many: exit(0) +EOF +pass; diff --git a/src/tests/userprog/args-multiple.ck b/src/tests/userprog/args-multiple.ck new file mode 100644 index 0000000..227e6cc --- /dev/null +++ b/src/tests/userprog/args-multiple.ck @@ -0,0 +1,17 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(args) begin +(args) argc = 5 +(args) argv[0] = 'args-multiple' +(args) argv[1] = 'some' +(args) argv[2] = 'arguments' +(args) argv[3] = 'for' +(args) argv[4] = 'you!' +(args) argv[5] = null +(args) end +args-multiple: exit(0) +EOF +pass; diff --git a/src/tests/userprog/args-none.ck b/src/tests/userprog/args-none.ck new file mode 100644 index 0000000..146318e --- /dev/null +++ b/src/tests/userprog/args-none.ck @@ -0,0 +1,13 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(args) begin +(args) argc = 1 +(args) argv[0] = 'args-none' +(args) argv[1] = null +(args) end +args-none: exit(0) +EOF +pass; diff --git a/src/tests/userprog/args-single.ck b/src/tests/userprog/args-single.ck new file mode 100644 index 0000000..24582b4 --- /dev/null +++ b/src/tests/userprog/args-single.ck @@ -0,0 +1,14 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(args) begin +(args) argc = 2 +(args) argv[0] = 'args-single' +(args) argv[1] = 'onearg' +(args) argv[2] = null +(args) end +args-single: exit(0) +EOF +pass; diff --git a/src/tests/userprog/args.c b/src/tests/userprog/args.c new file mode 100644 index 0000000..20eda44 --- /dev/null +++ b/src/tests/userprog/args.c @@ -0,0 +1,25 @@ +/* Prints the command-line arguments. + This program is used for all of the args-* tests. Grading is + done differently for each of the args-* tests based on the + output. */ + +#include "tests/lib.h" + +int +main (int argc, char *argv[]) +{ + int i; + + test_name = "args"; + + msg ("begin"); + msg ("argc = %d", argc); + for (i = 0; i <= argc; i++) + if (argv[i] != NULL) + msg ("argv[%d] = '%s'", i, argv[i]); + else + msg ("argv[%d] = null", i); + msg ("end"); + + return 0; +} diff --git a/src/tests/userprog/bad-jump.c b/src/tests/userprog/bad-jump.c new file mode 100644 index 0000000..51b7c9f --- /dev/null +++ b/src/tests/userprog/bad-jump.c @@ -0,0 +1,13 @@ +/* This program attempts to execute code at address 0, which is not mapped. + This should terminate the process with a -1 exit code. */ + +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + msg ("Congratulations - you have successfully called NULL: %d", + ((int (*)(void))NULL)()); + fail ("should have exited with -1"); +} diff --git a/src/tests/userprog/bad-jump.ck b/src/tests/userprog/bad-jump.ck new file mode 100644 index 0000000..e1c178b --- /dev/null +++ b/src/tests/userprog/bad-jump.ck @@ -0,0 +1,9 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']); +(bad-jump) begin +bad-jump: exit(-1) +EOF +pass; diff --git a/src/tests/userprog/bad-jump2.c b/src/tests/userprog/bad-jump2.c new file mode 100644 index 0000000..dc7c2a7 --- /dev/null +++ b/src/tests/userprog/bad-jump2.c @@ -0,0 +1,13 @@ +/* This program attempts to execute code at a kernel virtual address. + This should terminate the process with a -1 exit code. */ + +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + msg ("Congratulations - you have successfully called kernel code: %d", + ((int (*)(void))0xC0000000)()); + fail ("should have exited with -1"); +} diff --git a/src/tests/userprog/bad-jump2.ck b/src/tests/userprog/bad-jump2.ck new file mode 100644 index 0000000..35f0f97 --- /dev/null +++ b/src/tests/userprog/bad-jump2.ck @@ -0,0 +1,9 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']); +(bad-jump2) begin +bad-jump2: exit(-1) +EOF +pass; diff --git a/src/tests/userprog/bad-read.c b/src/tests/userprog/bad-read.c new file mode 100644 index 0000000..904c278 --- /dev/null +++ b/src/tests/userprog/bad-read.c @@ -0,0 +1,13 @@ +/* This program attempts to read memory at an address that is not mapped. + This should terminate the process with a -1 exit code. */ + +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + msg ("Congratulations - you have successfully dereferenced NULL: %d", + *(int *)NULL); + fail ("should have exited with -1"); +} diff --git a/src/tests/userprog/bad-read.ck b/src/tests/userprog/bad-read.ck new file mode 100644 index 0000000..4d4d926 --- /dev/null +++ b/src/tests/userprog/bad-read.ck @@ -0,0 +1,9 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']); +(bad-read) begin +bad-read: exit(-1) +EOF +pass; diff --git a/src/tests/userprog/bad-read2.c b/src/tests/userprog/bad-read2.c new file mode 100644 index 0000000..a2fc237 --- /dev/null +++ b/src/tests/userprog/bad-read2.c @@ -0,0 +1,13 @@ +/* This program attempts to read kernel memory. + This should terminate the process with a -1 exit code. */ + +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + msg ("Congratulations - you have successfully read kernel memory: %d", + *(int *)0xC0000000); + fail ("should have exited with -1"); +} diff --git a/src/tests/userprog/bad-read2.ck b/src/tests/userprog/bad-read2.ck new file mode 100644 index 0000000..fa27c7d --- /dev/null +++ b/src/tests/userprog/bad-read2.ck @@ -0,0 +1,9 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']); +(bad-read2) begin +bad-read2: exit(-1) +EOF +pass; diff --git a/src/tests/userprog/bad-write.c b/src/tests/userprog/bad-write.c new file mode 100644 index 0000000..000c26b --- /dev/null +++ b/src/tests/userprog/bad-write.c @@ -0,0 +1,12 @@ +/* This program attempts to write to memory at an address that is not mapped. + This should terminate the process with a -1 exit code. */ + +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + *(int *)NULL = 42; + fail ("should have exited with -1"); +} diff --git a/src/tests/userprog/bad-write.ck b/src/tests/userprog/bad-write.ck new file mode 100644 index 0000000..d213b49 --- /dev/null +++ b/src/tests/userprog/bad-write.ck @@ -0,0 +1,9 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']); +(bad-write) begin +bad-write: exit(-1) +EOF +pass; diff --git a/src/tests/userprog/bad-write2.c b/src/tests/userprog/bad-write2.c new file mode 100644 index 0000000..753da1e --- /dev/null +++ b/src/tests/userprog/bad-write2.c @@ -0,0 +1,12 @@ +/* This program attempts to write to kernel memory. + This should terminate the process with a -1 exit code. */ + +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + *(int *)0xC0000000 = 42; + fail ("should have exited with -1"); +} diff --git a/src/tests/userprog/bad-write2.ck b/src/tests/userprog/bad-write2.ck new file mode 100644 index 0000000..c6a3420 --- /dev/null +++ b/src/tests/userprog/bad-write2.ck @@ -0,0 +1,9 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']); +(bad-write2) begin +bad-write2: exit(-1) +EOF +pass; diff --git a/src/tests/userprog/boundary.c b/src/tests/userprog/boundary.c new file mode 100644 index 0000000..59907ec --- /dev/null +++ b/src/tests/userprog/boundary.c @@ -0,0 +1,33 @@ +/* Utility function for tests that try to break system calls by + passing them data that crosses from one virtual page to + another. */ + +#include +#include +#include +#include "tests/userprog/boundary.h" + +static char dst[8192]; + +/* Returns the beginning of a page. There are at least 2048 + modifiable bytes on either side of the pointer returned. */ +void * +get_boundary_area (void) +{ + char *p = (char *) ROUND_UP ((uintptr_t) dst, 4096); + if (p - dst < 2048) + p += 4096; + return p; +} + +/* Returns a copy of SRC split across the boundary between two + pages. */ +char * +copy_string_across_boundary (const char *src) +{ + char *p = get_boundary_area (); + p -= strlen (src) < 4096 ? strlen (src) / 2 : 4096; + strlcpy (p, src, 4096); + return p; +} + diff --git a/src/tests/userprog/boundary.h b/src/tests/userprog/boundary.h new file mode 100644 index 0000000..c8e4b3b --- /dev/null +++ b/src/tests/userprog/boundary.h @@ -0,0 +1,7 @@ +#ifndef TESTS_USERPROG_BOUNDARY_H +#define TESTS_USERPROG_BOUNDARY_H + +void *get_boundary_area (void); +char *copy_string_across_boundary (const char *); + +#endif /* tests/userprog/boundary.h */ diff --git a/src/tests/userprog/child-bad.c b/src/tests/userprog/child-bad.c new file mode 100644 index 0000000..77d7a69 --- /dev/null +++ b/src/tests/userprog/child-bad.c @@ -0,0 +1,14 @@ +/* Child process run by wait-killed test. + Sets the stack pointer (%esp) to an invalid value and invokes + a system call, which should then terminate the process with a + -1 exit code. */ + +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + asm volatile ("movl $0x20101234, %esp; int $0x30"); + fail ("should have exited with -1"); +} diff --git a/src/tests/userprog/child-close.c b/src/tests/userprog/child-close.c new file mode 100644 index 0000000..ac948c8 --- /dev/null +++ b/src/tests/userprog/child-close.c @@ -0,0 +1,28 @@ +/* Child process run by multi-child-fd test. + + Attempts to close the file descriptor passed as the first + command-line argument. This is invalid, because file + descriptors are not inherited in Pintos. Two results are + allowed: either the system call should return without taking + any action, or the kernel should terminate the process with a + -1 exit code. */ + +#include +#include +#include +#include +#include "tests/lib.h" + +const char *test_name = "child-close"; + +int +main (int argc UNUSED, char *argv[]) +{ + msg ("begin"); + if (!isdigit (*argv[1])) + fail ("bad command-line arguments"); + close (atoi (argv[1])); + msg ("end"); + + return 0; +} diff --git a/src/tests/userprog/child-rox.c b/src/tests/userprog/child-rox.c new file mode 100644 index 0000000..aba808b --- /dev/null +++ b/src/tests/userprog/child-rox.c @@ -0,0 +1,55 @@ +/* Child process run by rox-child and rox-multichild tests. + Opens and tries to write to its own executable, verifying that + that is disallowed. + Then recursively executes itself to the depth indicated by the + first command-line argument. */ + +#include +#include +#include +#include +#include "tests/lib.h" + +const char *test_name = "child-rox"; + +static void +try_write (void) +{ + int handle; + char buffer[19]; + + quiet = true; + CHECK ((handle = open ("child-rox")) > 1, "open \"child-rox\""); + quiet = false; + + CHECK (write (handle, buffer, sizeof buffer) == 0, + "try to write \"child-rox\""); + + close (handle); +} + +int +main (int argc UNUSED, char *argv[]) +{ + msg ("begin"); + try_write (); + + if (!isdigit (*argv[1])) + fail ("bad command-line arguments"); + if (atoi (argv[1]) > 1) + { + char cmd[128]; + int child; + + snprintf (cmd, sizeof cmd, "child-rox %d", atoi (argv[1]) - 1); + CHECK ((child = exec (cmd)) != -1, "exec \"%s\"", cmd); + quiet = true; + CHECK (wait (child) == 12, "wait for \"child-rox\""); + quiet = false; + } + + try_write (); + msg ("end"); + + return 12; +} diff --git a/src/tests/userprog/child-simple.c b/src/tests/userprog/child-simple.c new file mode 100644 index 0000000..0d2dacf --- /dev/null +++ b/src/tests/userprog/child-simple.c @@ -0,0 +1,15 @@ +/* Child process run by exec-multiple, exec-one, wait-simple, and + wait-twice tests. + Just prints a single message and terminates. */ + +#include +#include "tests/lib.h" + +const char *test_name = "child-simple"; + +int +main (void) +{ + msg ("run"); + return 81; +} diff --git a/src/tests/userprog/close-bad-fd.c b/src/tests/userprog/close-bad-fd.c new file mode 100644 index 0000000..f63bb9a --- /dev/null +++ b/src/tests/userprog/close-bad-fd.c @@ -0,0 +1,11 @@ +/* Tries to close an invalid fd, which must either fail silently + or terminate with exit code -1. */ + +#include +#include "tests/main.h" + +void +test_main (void) +{ + close (0x20101234); +} diff --git a/src/tests/userprog/close-bad-fd.ck b/src/tests/userprog/close-bad-fd.ck new file mode 100644 index 0000000..497b17c --- /dev/null +++ b/src/tests/userprog/close-bad-fd.ck @@ -0,0 +1,13 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF', <<'EOF']); +(close-bad-fd) begin +(close-bad-fd) end +close-bad-fd: exit(0) +EOF +(close-bad-fd) begin +close-bad-fd: exit(-1) +EOF +pass; diff --git a/src/tests/userprog/close-normal.c b/src/tests/userprog/close-normal.c new file mode 100644 index 0000000..8ce04e3 --- /dev/null +++ b/src/tests/userprog/close-normal.c @@ -0,0 +1,14 @@ +/* Opens a file and then closes it. */ + +#include +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + int handle; + CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); + msg ("close \"sample.txt\""); + close (handle); +} diff --git a/src/tests/userprog/close-normal.ck b/src/tests/userprog/close-normal.ck new file mode 100644 index 0000000..fe41342 --- /dev/null +++ b/src/tests/userprog/close-normal.ck @@ -0,0 +1,12 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(close-normal) begin +(close-normal) open "sample.txt" +(close-normal) close "sample.txt" +(close-normal) end +close-normal: exit(0) +EOF +pass; diff --git a/src/tests/userprog/close-stdin.c b/src/tests/userprog/close-stdin.c new file mode 100644 index 0000000..9bbf9f2 --- /dev/null +++ b/src/tests/userprog/close-stdin.c @@ -0,0 +1,11 @@ +/* Tries to close the keyboard input stream, which must either + fail silently or terminate with exit code -1. */ + +#include +#include "tests/main.h" + +void +test_main (void) +{ + close (0); +} diff --git a/src/tests/userprog/close-stdin.ck b/src/tests/userprog/close-stdin.ck new file mode 100644 index 0000000..3d28507 --- /dev/null +++ b/src/tests/userprog/close-stdin.ck @@ -0,0 +1,13 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF', <<'EOF']); +(close-stdin) begin +(close-stdin) end +close-stdin: exit(0) +EOF +(close-stdin) begin +close-stdin: exit(-1) +EOF +pass; diff --git a/src/tests/userprog/close-stdout.c b/src/tests/userprog/close-stdout.c new file mode 100644 index 0000000..886523f --- /dev/null +++ b/src/tests/userprog/close-stdout.c @@ -0,0 +1,11 @@ +/* Tries to close the console output stream, which must either + fail silently or terminate with exit code -1. */ + +#include +#include "tests/main.h" + +void +test_main (void) +{ + close (1); +} diff --git a/src/tests/userprog/close-stdout.ck b/src/tests/userprog/close-stdout.ck new file mode 100644 index 0000000..3cbbcff --- /dev/null +++ b/src/tests/userprog/close-stdout.ck @@ -0,0 +1,13 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF', <<'EOF']); +(close-stdout) begin +(close-stdout) end +close-stdout: exit(0) +EOF +(close-stdout) begin +close-stdout: exit(-1) +EOF +pass; diff --git a/src/tests/userprog/close-twice.c b/src/tests/userprog/close-twice.c new file mode 100644 index 0000000..830bccf --- /dev/null +++ b/src/tests/userprog/close-twice.c @@ -0,0 +1,18 @@ +/* Opens a file and then tries to close it twice. The second + close must either fail silently or terminate with exit code + -1. */ + +#include +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + int handle; + CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); + msg ("close \"sample.txt\""); + close (handle); + msg ("close \"sample.txt\" again"); + close (handle); +} diff --git a/src/tests/userprog/close-twice.ck b/src/tests/userprog/close-twice.ck new file mode 100644 index 0000000..deb55a6 --- /dev/null +++ b/src/tests/userprog/close-twice.ck @@ -0,0 +1,19 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF', <<'EOF']); +(close-twice) begin +(close-twice) open "sample.txt" +(close-twice) close "sample.txt" +(close-twice) close "sample.txt" again +(close-twice) end +close-twice: exit(0) +EOF +(close-twice) begin +(close-twice) open "sample.txt" +(close-twice) close "sample.txt" +(close-twice) close "sample.txt" again +close-twice: exit(-1) +EOF +pass; diff --git a/src/tests/userprog/create-bad-ptr.c b/src/tests/userprog/create-bad-ptr.c new file mode 100644 index 0000000..4a07bb3 --- /dev/null +++ b/src/tests/userprog/create-bad-ptr.c @@ -0,0 +1,12 @@ +/* Passes a bad pointer to the create system call, + which must cause the process to be terminated with exit code + -1. */ + +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + msg ("create(0x20101234): %d", create ((char *) 0x20101234, 0)); +} diff --git a/src/tests/userprog/create-bad-ptr.ck b/src/tests/userprog/create-bad-ptr.ck new file mode 100644 index 0000000..ac13405 --- /dev/null +++ b/src/tests/userprog/create-bad-ptr.ck @@ -0,0 +1,9 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(create-bad-ptr) begin +create-bad-ptr: exit(-1) +EOF +pass; diff --git a/src/tests/userprog/create-bound.c b/src/tests/userprog/create-bound.c new file mode 100644 index 0000000..0a829f3 --- /dev/null +++ b/src/tests/userprog/create-bound.c @@ -0,0 +1,14 @@ +/* Opens a file whose name spans the boundary between two pages. + This is valid, so it must succeed. */ + +#include +#include "tests/userprog/boundary.h" +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + msg ("create(\"quux.dat\"): %d", + create (copy_string_across_boundary ("quux.dat"), 0)); +} diff --git a/src/tests/userprog/create-bound.ck b/src/tests/userprog/create-bound.ck new file mode 100644 index 0000000..7656b7f --- /dev/null +++ b/src/tests/userprog/create-bound.ck @@ -0,0 +1,11 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(create-bound) begin +(create-bound) create("quux.dat"): 1 +(create-bound) end +create-bound: exit(0) +EOF +pass; diff --git a/src/tests/userprog/create-empty.c b/src/tests/userprog/create-empty.c new file mode 100644 index 0000000..fa26b43 --- /dev/null +++ b/src/tests/userprog/create-empty.c @@ -0,0 +1,10 @@ +/* Tries to create a file with the empty string as its name. */ + +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + msg ("create(\"\"): %d", create ("", 0)); +} diff --git a/src/tests/userprog/create-empty.ck b/src/tests/userprog/create-empty.ck new file mode 100644 index 0000000..93a1058 --- /dev/null +++ b/src/tests/userprog/create-empty.ck @@ -0,0 +1,14 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF', <<'EOF']); +(create-empty) begin +(create-empty) create(""): 0 +(create-empty) end +create-empty: exit(0) +EOF +(create-empty) begin +create-empty: exit(-1) +EOF +pass; diff --git a/src/tests/userprog/create-exists.c b/src/tests/userprog/create-exists.c new file mode 100644 index 0000000..d395008 --- /dev/null +++ b/src/tests/userprog/create-exists.c @@ -0,0 +1,16 @@ +/* Verifies that trying to create a file under a name that + already exists will fail. */ + +#include +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + CHECK (create ("quux.dat", 0), "create quux.dat"); + CHECK (create ("warble.dat", 0), "create warble.dat"); + CHECK (!create ("quux.dat", 0), "try to re-create quux.dat"); + CHECK (create ("baffle.dat", 0), "create baffle.dat"); + CHECK (!create ("warble.dat", 0), "try to re-create quux.dat"); +} diff --git a/src/tests/userprog/create-exists.ck b/src/tests/userprog/create-exists.ck new file mode 100644 index 0000000..006885e --- /dev/null +++ b/src/tests/userprog/create-exists.ck @@ -0,0 +1,15 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(create-exists) begin +(create-exists) create quux.dat +(create-exists) create warble.dat +(create-exists) try to re-create quux.dat +(create-exists) create baffle.dat +(create-exists) try to re-create quux.dat +(create-exists) end +create-exists: exit(0) +EOF +pass; diff --git a/src/tests/userprog/create-long.c b/src/tests/userprog/create-long.c new file mode 100644 index 0000000..16b31bd --- /dev/null +++ b/src/tests/userprog/create-long.c @@ -0,0 +1,17 @@ +/* Tries to create a file with a name that is much too long, + which must fail. */ + +#include +#include +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + static char name[512]; + memset (name, 'x', sizeof name); + name[sizeof name - 1] = '\0'; + + msg ("create(\"x...\"): %d", create (name, 0)); +} diff --git a/src/tests/userprog/create-long.ck b/src/tests/userprog/create-long.ck new file mode 100644 index 0000000..628411c --- /dev/null +++ b/src/tests/userprog/create-long.ck @@ -0,0 +1,11 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(create-long) begin +(create-long) create("x..."): 0 +(create-long) end +create-long: exit(0) +EOF +pass; diff --git a/src/tests/userprog/create-normal.c b/src/tests/userprog/create-normal.c new file mode 100644 index 0000000..3cbc463 --- /dev/null +++ b/src/tests/userprog/create-normal.c @@ -0,0 +1,10 @@ +/* Creates an ordinary empty file. */ + +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + CHECK (create ("quux.dat", 0), "create quux.dat"); +} diff --git a/src/tests/userprog/create-normal.ck b/src/tests/userprog/create-normal.ck new file mode 100644 index 0000000..ca74a6e --- /dev/null +++ b/src/tests/userprog/create-normal.ck @@ -0,0 +1,11 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(create-normal) begin +(create-normal) create quux.dat +(create-normal) end +create-normal: exit(0) +EOF +pass; diff --git a/src/tests/userprog/create-null.c b/src/tests/userprog/create-null.c new file mode 100644 index 0000000..287cb23 --- /dev/null +++ b/src/tests/userprog/create-null.c @@ -0,0 +1,11 @@ +/* Tries to create a file with the null pointer as its name. + The process must be terminated with exit code -1. */ + +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + msg ("create(NULL): %d", create (NULL, 0)); +} diff --git a/src/tests/userprog/create-null.ck b/src/tests/userprog/create-null.ck new file mode 100644 index 0000000..09b7872 --- /dev/null +++ b/src/tests/userprog/create-null.ck @@ -0,0 +1,9 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(create-null) begin +create-null: exit(-1) +EOF +pass; diff --git a/src/tests/userprog/exec-arg.c b/src/tests/userprog/exec-arg.c new file mode 100644 index 0000000..82d0744 --- /dev/null +++ b/src/tests/userprog/exec-arg.c @@ -0,0 +1,10 @@ +/* Tests argument passing to child processes. */ + +#include +#include "tests/main.h" + +void +test_main (void) +{ + wait (exec ("child-args childarg")); +} diff --git a/src/tests/userprog/exec-arg.ck b/src/tests/userprog/exec-arg.ck new file mode 100644 index 0000000..b7533ed --- /dev/null +++ b/src/tests/userprog/exec-arg.ck @@ -0,0 +1,17 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(exec-arg) begin +(args) begin +(args) argc = 2 +(args) argv[0] = 'child-args' +(args) argv[1] = 'childarg' +(args) argv[2] = null +(args) end +child-args: exit(0) +(exec-arg) end +exec-arg: exit(0) +EOF +pass; diff --git a/src/tests/userprog/exec-bad-ptr.c b/src/tests/userprog/exec-bad-ptr.c new file mode 100644 index 0000000..0abadd3 --- /dev/null +++ b/src/tests/userprog/exec-bad-ptr.c @@ -0,0 +1,11 @@ +/* Passes an invalid pointer to the exec system call. + The process must be terminated with -1 exit code. */ + +#include +#include "tests/main.h" + +void +test_main (void) +{ + exec ((char *) 0x20101234); +} diff --git a/src/tests/userprog/exec-bad-ptr.ck b/src/tests/userprog/exec-bad-ptr.ck new file mode 100644 index 0000000..63f5f78 --- /dev/null +++ b/src/tests/userprog/exec-bad-ptr.ck @@ -0,0 +1,13 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF', <<'EOF']); +(exec-bad-ptr) begin +(exec-bad-ptr) end +exec-bad-ptr: exit(0) +EOF +(exec-bad-ptr) begin +exec-bad-ptr: exit(-1) +EOF +pass; diff --git a/src/tests/userprog/exec-missing.c b/src/tests/userprog/exec-missing.c new file mode 100644 index 0000000..bf08cad --- /dev/null +++ b/src/tests/userprog/exec-missing.c @@ -0,0 +1,12 @@ +/* Tries to execute a nonexistent process. + The exec system call must return -1. */ + +#include +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + msg ("exec(\"no-such-file\"): %d", exec ("no-such-file")); +} diff --git a/src/tests/userprog/exec-missing.ck b/src/tests/userprog/exec-missing.ck new file mode 100644 index 0000000..0ef7aaa --- /dev/null +++ b/src/tests/userprog/exec-missing.ck @@ -0,0 +1,31 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF', <<'EOF', <<'EOF', <<'EOF']); +(exec-missing) begin +load: no-such-file: open failed +(exec-missing) exec("no-such-file"): -1 +(exec-missing) end +exec-missing: exit(0) +EOF +(exec-missing) begin +(exec-missing) exec("no-such-file"): -1 +(exec-missing) end +exec-missing: exit(0) +EOF +(exec-missing) begin +load: no-such-file: open failed +no-such-file: exit(-1) +(exec-missing) exec("no-such-file"): -1 +(exec-missing) end +exec-missing: exit(0) +EOF +(exec-missing) begin +load: no-such-file: open failed +(exec-missing) exec("no-such-file"): -1 +no-such-file: exit(-1) +(exec-missing) end +exec-missing: exit(0) +EOF +pass; diff --git a/src/tests/userprog/exec-multiple.c b/src/tests/userprog/exec-multiple.c new file mode 100644 index 0000000..ba4c26e --- /dev/null +++ b/src/tests/userprog/exec-multiple.c @@ -0,0 +1,14 @@ +/* Executes and waits for multiple child processes. */ + +#include +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + wait (exec ("child-simple")); + wait (exec ("child-simple")); + wait (exec ("child-simple")); + wait (exec ("child-simple")); +} diff --git a/src/tests/userprog/exec-multiple.ck b/src/tests/userprog/exec-multiple.ck new file mode 100644 index 0000000..99624cd --- /dev/null +++ b/src/tests/userprog/exec-multiple.ck @@ -0,0 +1,18 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(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) +EOF +pass; diff --git a/src/tests/userprog/exec-once.c b/src/tests/userprog/exec-once.c new file mode 100644 index 0000000..7bae5a1 --- /dev/null +++ b/src/tests/userprog/exec-once.c @@ -0,0 +1,11 @@ +/* Executes and waits for a single child process. */ + +#include +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + wait (exec ("child-simple")); +} diff --git a/src/tests/userprog/exec-once.ck b/src/tests/userprog/exec-once.ck new file mode 100644 index 0000000..00b59ed --- /dev/null +++ b/src/tests/userprog/exec-once.ck @@ -0,0 +1,12 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(exec-once) begin +(child-simple) run +child-simple: exit(81) +(exec-once) end +exec-once: exit(0) +EOF +pass; diff --git a/src/tests/userprog/exit.c b/src/tests/userprog/exit.c new file mode 100644 index 0000000..cb4eb8f --- /dev/null +++ b/src/tests/userprog/exit.c @@ -0,0 +1,11 @@ +/* Tests the exit system call. */ + +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + exit (57); + fail ("should have called exit(57)"); +} diff --git a/src/tests/userprog/exit.ck b/src/tests/userprog/exit.ck new file mode 100644 index 0000000..a552702 --- /dev/null +++ b/src/tests/userprog/exit.ck @@ -0,0 +1,9 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(exit) begin +exit: exit(57) +EOF +pass; diff --git a/src/tests/userprog/halt.c b/src/tests/userprog/halt.c new file mode 100644 index 0000000..4a99bce --- /dev/null +++ b/src/tests/userprog/halt.c @@ -0,0 +1,11 @@ +/* Tests the halt system call. */ + +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + halt (); + fail ("should have halted"); +} diff --git a/src/tests/userprog/halt.ck b/src/tests/userprog/halt.ck new file mode 100644 index 0000000..1b701ed --- /dev/null +++ b/src/tests/userprog/halt.ck @@ -0,0 +1,15 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; + +our ($test); +my (@output) = read_text_file ("$test.output"); + +common_checks ("run", @output); + +fail "missing 'begin' message\n" + if !grep ($_ eq '(halt) begin', @output); +fail "found 'fail' message--halt didn't really halt\n" + if grep ($_ eq '(halt) fail', @output); +pass; diff --git a/src/tests/userprog/lib/.cvsignore b/src/tests/userprog/lib/.cvsignore new file mode 100644 index 0000000..a438335 --- /dev/null +++ b/src/tests/userprog/lib/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/src/tests/userprog/lib/user/.cvsignore b/src/tests/userprog/lib/user/.cvsignore new file mode 100644 index 0000000..a438335 --- /dev/null +++ b/src/tests/userprog/lib/user/.cvsignore @@ -0,0 +1 @@ +*.d diff --git a/src/tests/userprog/lib/user/.dummy b/src/tests/userprog/lib/user/.dummy new file mode 100644 index 0000000..e69de29 diff --git a/src/tests/userprog/multi-child-fd.c b/src/tests/userprog/multi-child-fd.c new file mode 100644 index 0000000..48de4b4 --- /dev/null +++ b/src/tests/userprog/multi-child-fd.c @@ -0,0 +1,25 @@ +/* Opens a file and then runs a subprocess that tries to close + the file. (Pintos does not have inheritance of file handles, + so this must fail.) The parent process then attempts to use + the file handle, which must succeed. */ + +#include +#include +#include "tests/userprog/sample.inc" +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + char child_cmd[128]; + int handle; + + CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); + + snprintf (child_cmd, sizeof child_cmd, "child-close %d", handle); + + msg ("wait(exec()) = %d", wait (exec (child_cmd))); + + check_file_handle (handle, "sample.txt", sample, sizeof sample - 1); +} diff --git a/src/tests/userprog/multi-child-fd.ck b/src/tests/userprog/multi-child-fd.ck new file mode 100644 index 0000000..d0b3a33 --- /dev/null +++ b/src/tests/userprog/multi-child-fd.ck @@ -0,0 +1,25 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF', <<'EOF']); +(multi-child-fd) begin +(multi-child-fd) open "sample.txt" +(child-close) begin +(child-close) end +child-close: exit(0) +(multi-child-fd) wait(exec()) = 0 +(multi-child-fd) verified contents of "sample.txt" +(multi-child-fd) end +multi-child-fd: exit(0) +EOF +(multi-child-fd) begin +(multi-child-fd) open "sample.txt" +(child-close) begin +child-close: exit(-1) +(multi-child-fd) wait(exec()) = -1 +(multi-child-fd) verified contents of "sample.txt" +(multi-child-fd) end +multi-child-fd: exit(0) +EOF +pass; diff --git a/src/tests/userprog/multi-recurse.c b/src/tests/userprog/multi-recurse.c new file mode 100644 index 0000000..7172ec3 --- /dev/null +++ b/src/tests/userprog/multi-recurse.c @@ -0,0 +1,34 @@ +/* Executes itself recursively to the depth indicated by the + first command-line argument. */ + +#include +#include +#include +#include +#include "tests/lib.h" + +const char *test_name = "multi-recurse"; + +int +main (int argc UNUSED, char *argv[]) +{ + int n = atoi (argv[1]); + + msg ("begin %d", n); + if (n != 0) + { + char child_cmd[128]; + pid_t child_pid; + int code; + + snprintf (child_cmd, sizeof child_cmd, "multi-recurse %d", n - 1); + CHECK ((child_pid = exec (child_cmd)) != -1, "exec(\"%s\")", child_cmd); + + code = wait (child_pid); + if (code != n - 1) + fail ("wait(exec(\"%s\")) returned %d", child_cmd, code); + } + + msg ("end %d", n); + return n; +} diff --git a/src/tests/userprog/multi-recurse.ck b/src/tests/userprog/multi-recurse.ck new file mode 100644 index 0000000..41eb4a6 --- /dev/null +++ b/src/tests/userprog/multi-recurse.ck @@ -0,0 +1,70 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(multi-recurse) begin 15 +(multi-recurse) exec("multi-recurse 14") +(multi-recurse) begin 14 +(multi-recurse) exec("multi-recurse 13") +(multi-recurse) begin 13 +(multi-recurse) exec("multi-recurse 12") +(multi-recurse) begin 12 +(multi-recurse) exec("multi-recurse 11") +(multi-recurse) begin 11 +(multi-recurse) exec("multi-recurse 10") +(multi-recurse) begin 10 +(multi-recurse) exec("multi-recurse 9") +(multi-recurse) begin 9 +(multi-recurse) exec("multi-recurse 8") +(multi-recurse) begin 8 +(multi-recurse) exec("multi-recurse 7") +(multi-recurse) begin 7 +(multi-recurse) exec("multi-recurse 6") +(multi-recurse) begin 6 +(multi-recurse) exec("multi-recurse 5") +(multi-recurse) begin 5 +(multi-recurse) exec("multi-recurse 4") +(multi-recurse) begin 4 +(multi-recurse) exec("multi-recurse 3") +(multi-recurse) begin 3 +(multi-recurse) exec("multi-recurse 2") +(multi-recurse) begin 2 +(multi-recurse) exec("multi-recurse 1") +(multi-recurse) begin 1 +(multi-recurse) exec("multi-recurse 0") +(multi-recurse) begin 0 +(multi-recurse) end 0 +multi-recurse: exit(0) +(multi-recurse) end 1 +multi-recurse: exit(1) +(multi-recurse) end 2 +multi-recurse: exit(2) +(multi-recurse) end 3 +multi-recurse: exit(3) +(multi-recurse) end 4 +multi-recurse: exit(4) +(multi-recurse) end 5 +multi-recurse: exit(5) +(multi-recurse) end 6 +multi-recurse: exit(6) +(multi-recurse) end 7 +multi-recurse: exit(7) +(multi-recurse) end 8 +multi-recurse: exit(8) +(multi-recurse) end 9 +multi-recurse: exit(9) +(multi-recurse) end 10 +multi-recurse: exit(10) +(multi-recurse) end 11 +multi-recurse: exit(11) +(multi-recurse) end 12 +multi-recurse: exit(12) +(multi-recurse) end 13 +multi-recurse: exit(13) +(multi-recurse) end 14 +multi-recurse: exit(14) +(multi-recurse) end 15 +multi-recurse: exit(15) +EOF +pass; diff --git a/src/tests/userprog/no-vm/Make.tests b/src/tests/userprog/no-vm/Make.tests new file mode 100644 index 0000000..a545e18 --- /dev/null +++ b/src/tests/userprog/no-vm/Make.tests @@ -0,0 +1,8 @@ +# -*- makefile -*- + +tests/userprog/no-vm_TESTS = tests/userprog/no-vm/multi-oom +tests/userprog/no-vm_PROGS = $(tests/userprog/no-vm_TESTS) +tests/userprog/no-vm/multi-oom_SRC = tests/userprog/no-vm/multi-oom.c \ +tests/lib.c + +tests/userprog/no-vm/multi-oom.output: TIMEOUT = 360 diff --git a/src/tests/userprog/no-vm/Rubric b/src/tests/userprog/no-vm/Rubric new file mode 100644 index 0000000..c3816c6 --- /dev/null +++ b/src/tests/userprog/no-vm/Rubric @@ -0,0 +1,3 @@ +Functionality of features that VM might break: + +1 multi-oom diff --git a/src/tests/userprog/no-vm/multi-oom.c b/src/tests/userprog/no-vm/multi-oom.c new file mode 100644 index 0000000..6a4472d --- /dev/null +++ b/src/tests/userprog/no-vm/multi-oom.c @@ -0,0 +1,179 @@ +/* Recursively executes itself until the child fails to execute. + We expect that at least 30 copies can run. + + We count how many children your kernel was able to execute + before it fails to start a new process. We require that, + if a process doesn't actually get to start, exec() must + return -1, not a valid PID. + + We repeat this process 10 times, checking that your kernel + allows for the same level of depth every time. + + In addition, some processes will spawn children that terminate + abnormally after allocating some resources. + + Written by Godmar Back + */ + +#include +#include +#include +#include +#include +#include +#include +#include "tests/lib.h" + +static const int EXPECTED_DEPTH_TO_PASS = 30; +static const int EXPECTED_REPETITIONS = 10; + +const char *test_name = "multi-oom"; + +enum child_termination_mode { RECURSE, CRASH }; + +/* Spawn a recursive copy of ourselves, passing along instructions + for the child. */ +static pid_t +spawn_child (int c, enum child_termination_mode mode) +{ + char child_cmd[128]; + snprintf (child_cmd, sizeof child_cmd, + "%s %d %s", test_name, c, mode == CRASH ? "-k" : ""); + return exec (child_cmd); +} + +/* Open a number of files (and fail to close them). + The kernel must free any kernel resources associated + with these file descriptors. */ +static void +consume_some_resources (void) +{ + int fd, fdmax = 126; + + /* Open as many files as we can, up to fdmax. + Depending on how file descriptors are allocated inside + the kernel, open() may fail if the kernel is low on memory. + A low-memory condition in open() should not lead to the + termination of the process. */ + for (fd = 0; fd < fdmax; fd++) + if (open (test_name) == -1) + break; +} + +/* Consume some resources, then terminate this process + in some abnormal way. */ +static int NO_INLINE +consume_some_resources_and_die (int seed) +{ + consume_some_resources (); + random_init (seed); + int *PHYS_BASE = (int *)0xC0000000; + + switch (random_ulong () % 5) + { + case 0: + *(int *) NULL = 42; + + case 1: + return *(int *) NULL; + + case 2: + return *PHYS_BASE; + + case 3: + *PHYS_BASE = 42; + + case 4: + open ((char *)PHYS_BASE); + exit (-1); + + default: + NOT_REACHED (); + } + return 0; +} + +/* The first copy is invoked without command line arguments. + Subsequent copies are invoked with a parameter 'depth' + that describes how many parent processes preceded them. + Each process spawns one or multiple recursive copies of + itself, passing 'depth+1' as depth. + + Some children are started with the '-k' flag, which will + result in abnormal termination. + */ +int +main (int argc, char *argv[]) +{ + int n; + + n = argc > 1 ? atoi (argv[1]) : 0; + bool is_at_root = (n == 0); + if (is_at_root) + msg ("begin"); + + /* If -k is passed, crash this process. */ + if (argc > 2 && !strcmp(argv[2], "-k")) + { + consume_some_resources_and_die (n); + NOT_REACHED (); + } + + int howmany = is_at_root ? EXPECTED_REPETITIONS : 1; + int i, expected_depth = -1; + + for (i = 0; i < howmany; i++) + { + pid_t child_pid; + + /* Spawn a child that will be abnormally terminated. + To speed the test up, do this only for processes + spawned at a certain depth. */ + if (n > EXPECTED_DEPTH_TO_PASS/2) + { + child_pid = spawn_child (n + 1, CRASH); + if (child_pid != -1) + { + if (wait (child_pid) != -1) + fail ("crashed child should return -1."); + } + /* If spawning this child failed, so should + the next spawn_child below. */ + } + + /* Now spawn the child that will recurse. */ + child_pid = spawn_child (n + 1, RECURSE); + + /* If maximum depth is reached, return result. */ + if (child_pid == -1) + return n; + + /* Else wait for child to report how deeply it was able to recurse. */ + int reached_depth = wait (child_pid); + if (reached_depth == -1) + fail ("wait returned -1."); + + /* Record the depth reached during the first run; on subsequent + runs, fail if those runs do not match the depth achieved on the + first run. */ + if (i == 0) + expected_depth = reached_depth; + else if (expected_depth != reached_depth) + fail ("after run %d/%d, expected depth %d, actual depth %d.", + i, howmany, expected_depth, reached_depth); + ASSERT (expected_depth == reached_depth); + } + + consume_some_resources (); + + if (n == 0) + { + if (expected_depth < EXPECTED_DEPTH_TO_PASS) + fail ("should have forked at least %d times.", EXPECTED_DEPTH_TO_PASS); + msg ("success. program forked %d times.", howmany); + msg ("end"); + } + + return expected_depth; +} +// vim: sw=2 diff --git a/src/tests/userprog/no-vm/multi-oom.ck b/src/tests/userprog/no-vm/multi-oom.ck new file mode 100644 index 0000000..59a0bcd --- /dev/null +++ b/src/tests/userprog/no-vm/multi-oom.ck @@ -0,0 +1,10 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_USER_FAULTS => 1, IGNORE_EXIT_CODES => 1, [<<'EOF']); +(multi-oom) begin +(multi-oom) success. program forked 10 times. +(multi-oom) end +EOF +pass; diff --git a/src/tests/userprog/null.ck b/src/tests/userprog/null.ck new file mode 100644 index 0000000..980de35 --- /dev/null +++ b/src/tests/userprog/null.ck @@ -0,0 +1,8 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +system call! +EOF +pass; diff --git a/src/tests/userprog/open-bad-ptr.c b/src/tests/userprog/open-bad-ptr.c new file mode 100644 index 0000000..9cd4edf --- /dev/null +++ b/src/tests/userprog/open-bad-ptr.c @@ -0,0 +1,13 @@ +/* Passes an invalid pointer to the open system call. + The process must be terminated with -1 exit code. */ + +#include +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + msg ("open(0x20101234): %d", open ((char *) 0x20101234)); + fail ("should have called exit(-1)"); +} diff --git a/src/tests/userprog/open-bad-ptr.ck b/src/tests/userprog/open-bad-ptr.ck new file mode 100644 index 0000000..45349e2 --- /dev/null +++ b/src/tests/userprog/open-bad-ptr.ck @@ -0,0 +1,13 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF', <<'EOF']); +(open-bad-ptr) begin +(open-bad-ptr) end +open-bad-ptr: exit(0) +EOF +(open-bad-ptr) begin +open-bad-ptr: exit(-1) +EOF +pass; diff --git a/src/tests/userprog/open-boundary.c b/src/tests/userprog/open-boundary.c new file mode 100644 index 0000000..cc8ff8b --- /dev/null +++ b/src/tests/userprog/open-boundary.c @@ -0,0 +1,14 @@ +/* Creates a file whose name spans the boundary between two pages. + This is valid, so it must succeed. */ + +#include +#include "tests/userprog/boundary.h" +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + CHECK (open (copy_string_across_boundary ("sample.txt")) > 1, + "open \"sample.txt\""); +} diff --git a/src/tests/userprog/open-boundary.ck b/src/tests/userprog/open-boundary.ck new file mode 100644 index 0000000..8060d22 --- /dev/null +++ b/src/tests/userprog/open-boundary.ck @@ -0,0 +1,11 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(open-boundary) begin +(open-boundary) open "sample.txt" +(open-boundary) end +open-boundary: exit(0) +EOF +pass; diff --git a/src/tests/userprog/open-empty.c b/src/tests/userprog/open-empty.c new file mode 100644 index 0000000..3ea9907 --- /dev/null +++ b/src/tests/userprog/open-empty.c @@ -0,0 +1,13 @@ +/* Tries to open a file with the empty string as its name. */ + +#include +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + int handle = open (""); + if (handle != -1) + fail ("open() returned %d instead of -1", handle); +} diff --git a/src/tests/userprog/open-empty.ck b/src/tests/userprog/open-empty.ck new file mode 100644 index 0000000..885fb41 --- /dev/null +++ b/src/tests/userprog/open-empty.ck @@ -0,0 +1,10 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(open-empty) begin +(open-empty) end +open-empty: exit(0) +EOF +pass; diff --git a/src/tests/userprog/open-missing.c b/src/tests/userprog/open-missing.c new file mode 100644 index 0000000..13ecbda --- /dev/null +++ b/src/tests/userprog/open-missing.c @@ -0,0 +1,13 @@ +/* Tries to open a nonexistent file. */ + +#include +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + int handle = open ("no-such-file"); + if (handle != -1) + fail ("open() returned %d", handle); +} diff --git a/src/tests/userprog/open-missing.ck b/src/tests/userprog/open-missing.ck new file mode 100644 index 0000000..d72d878 --- /dev/null +++ b/src/tests/userprog/open-missing.ck @@ -0,0 +1,10 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(open-missing) begin +(open-missing) end +open-missing: exit(0) +EOF +pass; diff --git a/src/tests/userprog/open-normal.c b/src/tests/userprog/open-normal.c new file mode 100644 index 0000000..5132465 --- /dev/null +++ b/src/tests/userprog/open-normal.c @@ -0,0 +1,13 @@ +/* Open a file. */ + +#include +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + int handle = open ("sample.txt"); + if (handle < 2) + fail ("open() returned %d", handle); +} diff --git a/src/tests/userprog/open-normal.ck b/src/tests/userprog/open-normal.ck new file mode 100644 index 0000000..4f6c342 --- /dev/null +++ b/src/tests/userprog/open-normal.ck @@ -0,0 +1,10 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(open-normal) begin +(open-normal) end +open-normal: exit(0) +EOF +pass; diff --git a/src/tests/userprog/open-null.c b/src/tests/userprog/open-null.c new file mode 100644 index 0000000..bb418b8 --- /dev/null +++ b/src/tests/userprog/open-null.c @@ -0,0 +1,12 @@ +/* Tries to open a file with the null pointer as its name. + The process must be terminated with exit code -1. */ + +#include +#include +#include "tests/main.h" + +void +test_main (void) +{ + open (NULL); +} diff --git a/src/tests/userprog/open-null.ck b/src/tests/userprog/open-null.ck new file mode 100644 index 0000000..b4a3bcb --- /dev/null +++ b/src/tests/userprog/open-null.ck @@ -0,0 +1,13 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF', <<'EOF']); +(open-null) begin +(open-null) end +open-null: exit(0) +EOF +(open-null) begin +open-null: exit(-1) +EOF +pass; diff --git a/src/tests/userprog/open-twice.c b/src/tests/userprog/open-twice.c new file mode 100644 index 0000000..dd333af --- /dev/null +++ b/src/tests/userprog/open-twice.c @@ -0,0 +1,19 @@ +/* Tries to open the same file twice, + which must succeed and must return a different file descriptor + in each case. */ + +#include +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + int h1 = open ("sample.txt"); + int h2 = open ("sample.txt"); + + CHECK ((h1 = open ("sample.txt")) > 1, "open \"sample.txt\" once"); + CHECK ((h2 = open ("sample.txt")) > 1, "open \"sample.txt\" again"); + if (h1 == h2) + fail ("open() returned %d both times", h1); +} diff --git a/src/tests/userprog/open-twice.ck b/src/tests/userprog/open-twice.ck new file mode 100644 index 0000000..64fa805 --- /dev/null +++ b/src/tests/userprog/open-twice.ck @@ -0,0 +1,12 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(open-twice) begin +(open-twice) open "sample.txt" once +(open-twice) open "sample.txt" again +(open-twice) end +open-twice: exit(0) +EOF +pass; diff --git a/src/tests/userprog/read-bad-fd.c b/src/tests/userprog/read-bad-fd.c new file mode 100644 index 0000000..a8b190d --- /dev/null +++ b/src/tests/userprog/read-bad-fd.c @@ -0,0 +1,21 @@ +/* Tries to read from an invalid fd, + which must either fail silently or terminate the process with + exit code -1. */ + +#include +#include +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + char buf; + read (0x20101234, &buf, 1); + read (5, &buf, 1); + read (1234, &buf, 1); + read (-1, &buf, 1); + read (-1024, &buf, 1); + read (INT_MIN, &buf, 1); + read (INT_MAX, &buf, 1); +} diff --git a/src/tests/userprog/read-bad-fd.ck b/src/tests/userprog/read-bad-fd.ck new file mode 100644 index 0000000..5fedcc7 --- /dev/null +++ b/src/tests/userprog/read-bad-fd.ck @@ -0,0 +1,13 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF', <<'EOF']); +(read-bad-fd) begin +(read-bad-fd) end +read-bad-fd: exit(0) +EOF +(read-bad-fd) begin +read-bad-fd: exit(-1) +EOF +pass; diff --git a/src/tests/userprog/read-bad-ptr.c b/src/tests/userprog/read-bad-ptr.c new file mode 100644 index 0000000..8fe756e --- /dev/null +++ b/src/tests/userprog/read-bad-ptr.c @@ -0,0 +1,16 @@ +/* Passes an invalid pointer to the read system call. + The process must be terminated with -1 exit code. */ + +#include +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + int handle; + CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); + + read (handle, (char *) 0xc0100000, 123); + fail ("should not have survived read()"); +} diff --git a/src/tests/userprog/read-bad-ptr.ck b/src/tests/userprog/read-bad-ptr.ck new file mode 100644 index 0000000..d10accf --- /dev/null +++ b/src/tests/userprog/read-bad-ptr.ck @@ -0,0 +1,15 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF', <<'EOF']); +(read-bad-ptr) begin +(read-bad-ptr) open "sample.txt" +(read-bad-ptr) end +read-bad-ptr: exit(0) +EOF +(read-bad-ptr) begin +(read-bad-ptr) open "sample.txt" +read-bad-ptr: exit(-1) +EOF +pass; diff --git a/src/tests/userprog/read-boundary.c b/src/tests/userprog/read-boundary.c new file mode 100644 index 0000000..9c19966 --- /dev/null +++ b/src/tests/userprog/read-boundary.c @@ -0,0 +1,30 @@ +/* Reads data spanning two pages in virtual address space, + which must succeed. */ + +#include +#include +#include "tests/userprog/boundary.h" +#include "tests/userprog/sample.inc" +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + int handle; + int byte_cnt; + char *buffer; + + CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); + + buffer = get_boundary_area () - sizeof sample / 2; + byte_cnt = read (handle, buffer, sizeof sample - 1); + if (byte_cnt != sizeof sample - 1) + fail ("read() returned %d instead of %zu", byte_cnt, sizeof sample - 1); + else if (strcmp (sample, buffer)) + { + msg ("expected text:\n%s", sample); + msg ("text actually read:\n%s", buffer); + fail ("expected text differs from actual"); + } +} diff --git a/src/tests/userprog/read-boundary.ck b/src/tests/userprog/read-boundary.ck new file mode 100644 index 0000000..08dc161 --- /dev/null +++ b/src/tests/userprog/read-boundary.ck @@ -0,0 +1,11 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(read-boundary) begin +(read-boundary) open "sample.txt" +(read-boundary) end +read-boundary: exit(0) +EOF +pass; diff --git a/src/tests/userprog/read-normal.c b/src/tests/userprog/read-normal.c new file mode 100644 index 0000000..16d15cc --- /dev/null +++ b/src/tests/userprog/read-normal.c @@ -0,0 +1,11 @@ +/* Try reading a file in the most normal way. */ + +#include "tests/userprog/sample.inc" +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + check_file ("sample.txt", sample, sizeof sample - 1); +} diff --git a/src/tests/userprog/read-normal.ck b/src/tests/userprog/read-normal.ck new file mode 100644 index 0000000..0ed2998 --- /dev/null +++ b/src/tests/userprog/read-normal.ck @@ -0,0 +1,13 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(read-normal) begin +(read-normal) open "sample.txt" for verification +(read-normal) verified contents of "sample.txt" +(read-normal) close "sample.txt" +(read-normal) end +read-normal: exit(0) +EOF +pass; diff --git a/src/tests/userprog/read-stdout.c b/src/tests/userprog/read-stdout.c new file mode 100644 index 0000000..d0630b9 --- /dev/null +++ b/src/tests/userprog/read-stdout.c @@ -0,0 +1,14 @@ +/* Try reading from fd 1 (stdout), + which may just fail or terminate the process with -1 exit + code. */ + +#include +#include +#include "tests/main.h" + +void +test_main (void) +{ + char buf; + read (STDOUT_FILENO, &buf, 1); +} diff --git a/src/tests/userprog/read-stdout.ck b/src/tests/userprog/read-stdout.ck new file mode 100644 index 0000000..7d87b52 --- /dev/null +++ b/src/tests/userprog/read-stdout.ck @@ -0,0 +1,13 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF', <<'EOF']); +(read-stdout) begin +(read-stdout) end +read-stdout: exit(0) +EOF +(read-stdout) begin +read-stdout: exit(-1) +EOF +pass; diff --git a/src/tests/userprog/read-zero.c b/src/tests/userprog/read-zero.c new file mode 100644 index 0000000..e441817 --- /dev/null +++ b/src/tests/userprog/read-zero.c @@ -0,0 +1,22 @@ +/* Try a 0-byte read, which should return 0 without reading + anything. */ + +#include +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + int handle, byte_cnt; + char buf; + + CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); + + buf = 123; + byte_cnt = read (handle, &buf, 0); + if (byte_cnt != 0) + fail ("read() returned %d instead of 0", byte_cnt); + else if (buf != 123) + fail ("0-byte read() modified buffer"); +} diff --git a/src/tests/userprog/read-zero.ck b/src/tests/userprog/read-zero.ck new file mode 100644 index 0000000..8346dbc --- /dev/null +++ b/src/tests/userprog/read-zero.ck @@ -0,0 +1,11 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(read-zero) begin +(read-zero) open "sample.txt" +(read-zero) end +read-zero: exit(0) +EOF +pass; diff --git a/src/tests/userprog/rox-child.c b/src/tests/userprog/rox-child.c new file mode 100644 index 0000000..30afba2 --- /dev/null +++ b/src/tests/userprog/rox-child.c @@ -0,0 +1,5 @@ +/* Ensure that the executable of a running process cannot be + modified, even by a child process. */ + +#define CHILD_CNT "1" +#include "tests/userprog/rox-child.inc" diff --git a/src/tests/userprog/rox-child.ck b/src/tests/userprog/rox-child.ck new file mode 100644 index 0000000..e6363fb --- /dev/null +++ b/src/tests/userprog/rox-child.ck @@ -0,0 +1,20 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(rox-child) begin +(rox-child) open "child-rox" +(rox-child) read "child-rox" +(rox-child) write "child-rox" +(rox-child) exec "child-rox 1" +(child-rox) begin +(child-rox) try to write "child-rox" +(child-rox) try to write "child-rox" +(child-rox) end +child-rox: exit(12) +(rox-child) write "child-rox" +(rox-child) end +rox-child: exit(0) +EOF +pass; diff --git a/src/tests/userprog/rox-child.inc b/src/tests/userprog/rox-child.inc new file mode 100644 index 0000000..1e2ade9 --- /dev/null +++ b/src/tests/userprog/rox-child.inc @@ -0,0 +1,33 @@ +/* -*- c -*- */ + +#include +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + const char *child_cmd = "child-rox " CHILD_CNT; + int handle; + pid_t child; + char buffer[16]; + + /* Open child-rox, read from it, write back same data. */ + CHECK ((handle = open ("child-rox")) > 1, "open \"child-rox\""); + CHECK (read (handle, buffer, sizeof buffer) == (int) sizeof buffer, + "read \"child-rox\""); + seek (handle, 0); + CHECK (write (handle, buffer, sizeof buffer) == (int) sizeof buffer, + "write \"child-rox\""); + + /* Execute child-rox and wait for it. */ + CHECK ((child = exec (child_cmd)) != -1, "exec \"%s\"", child_cmd); + quiet = true; + CHECK (wait (child) == 12, "wait for child"); + quiet = false; + + /* Write to child-rox again. */ + seek (handle, 0); + CHECK (write (handle, buffer, sizeof buffer) == (int) sizeof buffer, + "write \"child-rox\""); +} diff --git a/src/tests/userprog/rox-multichild.c b/src/tests/userprog/rox-multichild.c new file mode 100644 index 0000000..8e74dab --- /dev/null +++ b/src/tests/userprog/rox-multichild.c @@ -0,0 +1,5 @@ +/* Ensure that the executable of a running process cannot be + modified, even in the presence of multiple children. */ + +#define CHILD_CNT "5" +#include "tests/userprog/rox-child.inc" diff --git a/src/tests/userprog/rox-multichild.ck b/src/tests/userprog/rox-multichild.ck new file mode 100644 index 0000000..14b27db --- /dev/null +++ b/src/tests/userprog/rox-multichild.ck @@ -0,0 +1,44 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(rox-multichild) begin +(rox-multichild) open "child-rox" +(rox-multichild) read "child-rox" +(rox-multichild) write "child-rox" +(rox-multichild) exec "child-rox 5" +(child-rox) begin +(child-rox) try to write "child-rox" +(child-rox) exec "child-rox 4" +(child-rox) begin +(child-rox) try to write "child-rox" +(child-rox) exec "child-rox 3" +(child-rox) begin +(child-rox) try to write "child-rox" +(child-rox) exec "child-rox 2" +(child-rox) begin +(child-rox) try to write "child-rox" +(child-rox) exec "child-rox 1" +(child-rox) begin +(child-rox) try to write "child-rox" +(child-rox) try to write "child-rox" +(child-rox) end +child-rox: exit(12) +(child-rox) try to write "child-rox" +(child-rox) end +child-rox: exit(12) +(child-rox) try to write "child-rox" +(child-rox) end +child-rox: exit(12) +(child-rox) try to write "child-rox" +(child-rox) end +child-rox: exit(12) +(child-rox) try to write "child-rox" +(child-rox) end +child-rox: exit(12) +(rox-multichild) write "child-rox" +(rox-multichild) end +rox-multichild: exit(0) +EOF +pass; diff --git a/src/tests/userprog/rox-simple.c b/src/tests/userprog/rox-simple.c new file mode 100644 index 0000000..e84a064 --- /dev/null +++ b/src/tests/userprog/rox-simple.c @@ -0,0 +1,19 @@ +/* Ensure that the executable of a running process cannot be + modified. */ + +#include +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + int handle; + char buffer[16]; + + CHECK ((handle = open ("rox-simple")) > 1, "open \"rox-simple\""); + CHECK (read (handle, buffer, sizeof buffer) == (int) sizeof buffer, + "read \"rox-simple\""); + CHECK (write (handle, buffer, sizeof buffer) == 0, + "try to write \"rox-simple\""); +} diff --git a/src/tests/userprog/rox-simple.ck b/src/tests/userprog/rox-simple.ck new file mode 100644 index 0000000..c9dcc66 --- /dev/null +++ b/src/tests/userprog/rox-simple.ck @@ -0,0 +1,13 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(rox-simple) begin +(rox-simple) open "rox-simple" +(rox-simple) read "rox-simple" +(rox-simple) try to write "rox-simple" +(rox-simple) end +rox-simple: exit(0) +EOF +pass; diff --git a/src/tests/userprog/sample.inc b/src/tests/userprog/sample.inc new file mode 100644 index 0000000..59f2bcb --- /dev/null +++ b/src/tests/userprog/sample.inc @@ -0,0 +1,6 @@ +char sample[] = { + "\"Amazing Electronic Fact: If you scuffed your feet long enough without\n" + " touching anything, you would build up so many electrons that your\n" + " finger would explode! But this is nothing to worry about unless you\n" + " have carpeting.\" --Dave Barry\n" +}; diff --git a/src/tests/userprog/sample.txt b/src/tests/userprog/sample.txt new file mode 100644 index 0000000..5050fec --- /dev/null +++ b/src/tests/userprog/sample.txt @@ -0,0 +1,4 @@ +"Amazing Electronic Fact: If you scuffed your feet long enough without + touching anything, you would build up so many electrons that your + finger would explode! But this is nothing to worry about unless you + have carpeting." --Dave Barry diff --git a/src/tests/userprog/sc-bad-arg.c b/src/tests/userprog/sc-bad-arg.c new file mode 100644 index 0000000..0b512a0 --- /dev/null +++ b/src/tests/userprog/sc-bad-arg.c @@ -0,0 +1,17 @@ +/* Sticks a system call number (SYS_EXIT) at the very top of the + stack, then invokes a system call with the stack pointer + (%esp) set to its address. The process must be terminated + with -1 exit code because the argument to the system call + would be above the top of the user address space. */ + +#include +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + asm volatile ("movl $0xbffffffc, %%esp; movl %0, (%%esp); int $0x30" + : : "i" (SYS_EXIT)); + fail ("should have called exit(-1)"); +} diff --git a/src/tests/userprog/sc-bad-arg.ck b/src/tests/userprog/sc-bad-arg.ck new file mode 100644 index 0000000..8981105 --- /dev/null +++ b/src/tests/userprog/sc-bad-arg.ck @@ -0,0 +1,9 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(sc-bad-arg) begin +sc-bad-arg: exit(-1) +EOF +pass; diff --git a/src/tests/userprog/sc-bad-sp.c b/src/tests/userprog/sc-bad-sp.c new file mode 100644 index 0000000..39cce84 --- /dev/null +++ b/src/tests/userprog/sc-bad-sp.c @@ -0,0 +1,20 @@ +/* Invokes a system call with the stack pointer (%esp) set to a + bad address. The process must be terminated with -1 exit + code. + + For Project 3: The bad address lies approximately 64MB below + the code segment, so there is no ambiguity that this attempt + must be rejected even after stack growth is implemented. + Moreover, a good stack growth heuristics should probably not + grow the stack for the purpose of reading the system call + number and arguments. */ + +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + asm volatile ("movl $.-(64*1024*1024), %esp; int $0x30"); + fail ("should have called exit(-1)"); +} diff --git a/src/tests/userprog/sc-bad-sp.ck b/src/tests/userprog/sc-bad-sp.ck new file mode 100644 index 0000000..498cec1 --- /dev/null +++ b/src/tests/userprog/sc-bad-sp.ck @@ -0,0 +1,9 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(sc-bad-sp) begin +sc-bad-sp: exit(-1) +EOF +pass; diff --git a/src/tests/userprog/sc-boundary-2.c b/src/tests/userprog/sc-boundary-2.c new file mode 100644 index 0000000..8acf036 --- /dev/null +++ b/src/tests/userprog/sc-boundary-2.c @@ -0,0 +1,22 @@ +/* Invokes a system call with one byte of the system call's + argument on a separate page from the rest of the bytes. This + must work. */ + +#include +#include "tests/userprog/boundary.h" +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + /* Make one byte of a syscall argument hang over into a second + page. */ + int *p = (int *) ((char *) get_boundary_area () - 7); + p[0] = SYS_EXIT; + p[1] = 67; + + /* Invoke the system call. */ + asm volatile ("movl %0, %%esp; int $0x30" : : "g" (p)); + fail ("should have called exit(67)"); +} diff --git a/src/tests/userprog/sc-boundary-2.ck b/src/tests/userprog/sc-boundary-2.ck new file mode 100644 index 0000000..43766bf --- /dev/null +++ b/src/tests/userprog/sc-boundary-2.ck @@ -0,0 +1,9 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(sc-boundary-2) begin +sc-boundary-2: exit(67) +EOF +pass; diff --git a/src/tests/userprog/sc-boundary.c b/src/tests/userprog/sc-boundary.c new file mode 100644 index 0000000..d889535 --- /dev/null +++ b/src/tests/userprog/sc-boundary.c @@ -0,0 +1,22 @@ +/* Invokes a system call with the system call number and its + argument on separate pages. This must work. */ + +#include +#include "tests/userprog/boundary.h" +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + /* Put a syscall number at the end of one page + and its argument at the beginning of another. */ + int *p = get_boundary_area (); + p--; + p[0] = SYS_EXIT; + p[1] = 42; + + /* Invoke the system call. */ + asm volatile ("movl %0, %%esp; int $0x30" : : "g" (p)); + fail ("should have called exit(42)"); +} diff --git a/src/tests/userprog/sc-boundary.ck b/src/tests/userprog/sc-boundary.ck new file mode 100644 index 0000000..3f7cbaf --- /dev/null +++ b/src/tests/userprog/sc-boundary.ck @@ -0,0 +1,9 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(sc-boundary) begin +sc-boundary: exit(42) +EOF +pass; diff --git a/src/tests/userprog/wait-bad-pid.c b/src/tests/userprog/wait-bad-pid.c new file mode 100644 index 0000000..3fe8ee4 --- /dev/null +++ b/src/tests/userprog/wait-bad-pid.c @@ -0,0 +1,11 @@ +/* Waits for an invalid pid. This may fail or terminate the + process with -1 exit code. */ + +#include +#include "tests/main.h" + +void +test_main (void) +{ + wait ((pid_t) 0x0c020301); +} diff --git a/src/tests/userprog/wait-bad-pid.ck b/src/tests/userprog/wait-bad-pid.ck new file mode 100644 index 0000000..db63fb9 --- /dev/null +++ b/src/tests/userprog/wait-bad-pid.ck @@ -0,0 +1,13 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF', <<'EOF']); +(wait-bad-pid) begin +(wait-bad-pid) end +wait-bad-pid: exit(0) +EOF +(wait-bad-pid) begin +wait-bad-pid: exit(-1) +EOF +pass; diff --git a/src/tests/userprog/wait-killed.c b/src/tests/userprog/wait-killed.c new file mode 100644 index 0000000..6a2a6b5 --- /dev/null +++ b/src/tests/userprog/wait-killed.c @@ -0,0 +1,11 @@ +/* Wait for a process that will be killed for bad behavior. */ + +#include +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + msg ("wait(exec()) = %d", wait (exec ("child-bad"))); +} diff --git a/src/tests/userprog/wait-killed.ck b/src/tests/userprog/wait-killed.ck new file mode 100644 index 0000000..5df0e9c --- /dev/null +++ b/src/tests/userprog/wait-killed.ck @@ -0,0 +1,13 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(wait-killed) begin +(child-bad) begin +child-bad: exit(-1) +(wait-killed) wait(exec()) = -1 +(wait-killed) end +wait-killed: exit(0) +EOF +pass; diff --git a/src/tests/userprog/wait-simple.c b/src/tests/userprog/wait-simple.c new file mode 100644 index 0000000..d3afcf3 --- /dev/null +++ b/src/tests/userprog/wait-simple.c @@ -0,0 +1,11 @@ +/* Wait for a subprocess to finish. */ + +#include +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + msg ("wait(exec()) = %d", wait (exec ("child-simple"))); +} diff --git a/src/tests/userprog/wait-simple.ck b/src/tests/userprog/wait-simple.ck new file mode 100644 index 0000000..93dd577 --- /dev/null +++ b/src/tests/userprog/wait-simple.ck @@ -0,0 +1,13 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(wait-simple) begin +(child-simple) run +child-simple: exit(81) +(wait-simple) wait(exec()) = 81 +(wait-simple) end +wait-simple: exit(0) +EOF +pass; diff --git a/src/tests/userprog/wait-twice.c b/src/tests/userprog/wait-twice.c new file mode 100644 index 0000000..785e684 --- /dev/null +++ b/src/tests/userprog/wait-twice.c @@ -0,0 +1,15 @@ +/* Wait for a subprocess to finish, twice. + The first call must wait in the usual way and return the exit code. + The second wait call must return -1 immediately. */ + +#include +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + pid_t child = exec ("child-simple"); + msg ("wait(exec()) = %d", wait (child)); + msg ("wait(exec()) = %d", wait (child)); +} diff --git a/src/tests/userprog/wait-twice.ck b/src/tests/userprog/wait-twice.ck new file mode 100644 index 0000000..6d53843 --- /dev/null +++ b/src/tests/userprog/wait-twice.ck @@ -0,0 +1,14 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(wait-twice) begin +(child-simple) run +child-simple: exit(81) +(wait-twice) wait(exec()) = 81 +(wait-twice) wait(exec()) = -1 +(wait-twice) end +wait-twice: exit(0) +EOF +pass; diff --git a/src/tests/userprog/write-bad-fd.c b/src/tests/userprog/write-bad-fd.c new file mode 100644 index 0000000..f3b1151 --- /dev/null +++ b/src/tests/userprog/write-bad-fd.c @@ -0,0 +1,20 @@ +/* Tries to write to an invalid fd, + which must either fail silently or terminate the process with + exit code -1. */ + +#include +#include +#include "tests/main.h" + +void +test_main (void) +{ + char buf = 123; + write (0x01012342, &buf, 1); + write (7, &buf, 1); + write (2546, &buf, 1); + write (-5, &buf, 1); + write (-8192, &buf, 1); + write (INT_MIN + 1, &buf, 1); + write (INT_MAX - 1, &buf, 1); +} diff --git a/src/tests/userprog/write-bad-fd.ck b/src/tests/userprog/write-bad-fd.ck new file mode 100644 index 0000000..8da7a8b --- /dev/null +++ b/src/tests/userprog/write-bad-fd.ck @@ -0,0 +1,13 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF', <<'EOF']); +(write-bad-fd) begin +(write-bad-fd) end +write-bad-fd: exit(0) +EOF +(write-bad-fd) begin +write-bad-fd: exit(-1) +EOF +pass; diff --git a/src/tests/userprog/write-bad-ptr.c b/src/tests/userprog/write-bad-ptr.c new file mode 100644 index 0000000..5336479 --- /dev/null +++ b/src/tests/userprog/write-bad-ptr.c @@ -0,0 +1,16 @@ +/* Passes an invalid pointer to the write system call. + The process must be terminated with -1 exit code. */ + +#include +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + int handle; + CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); + + write (handle, (char *) 0x10123420, 123); + fail ("should have exited with -1"); +} diff --git a/src/tests/userprog/write-bad-ptr.ck b/src/tests/userprog/write-bad-ptr.ck new file mode 100644 index 0000000..ad9f399 --- /dev/null +++ b/src/tests/userprog/write-bad-ptr.ck @@ -0,0 +1,15 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF', <<'EOF']); +(write-bad-ptr) begin +(write-bad-ptr) open "sample.txt" +(write-bad-ptr) end +write-bad-ptr: exit(0) +EOF +(write-bad-ptr) begin +(write-bad-ptr) open "sample.txt" +write-bad-ptr: exit(-1) +EOF +pass; diff --git a/src/tests/userprog/write-boundary.c b/src/tests/userprog/write-boundary.c new file mode 100644 index 0000000..d2de1d4 --- /dev/null +++ b/src/tests/userprog/write-boundary.c @@ -0,0 +1,25 @@ +/* Writes data spanning two pages in virtual address space, + which must succeed. */ + +#include +#include +#include "tests/userprog/boundary.h" +#include "tests/userprog/sample.inc" +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + int handle; + int byte_cnt; + char *sample_p; + + sample_p = copy_string_across_boundary (sample); + + CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); + + byte_cnt = write (handle, sample_p, sizeof sample - 1); + if (byte_cnt != sizeof sample - 1) + fail ("write() returned %d instead of %zu", byte_cnt, sizeof sample - 1); +} diff --git a/src/tests/userprog/write-boundary.ck b/src/tests/userprog/write-boundary.ck new file mode 100644 index 0000000..7883781 --- /dev/null +++ b/src/tests/userprog/write-boundary.ck @@ -0,0 +1,11 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(write-boundary) begin +(write-boundary) open "sample.txt" +(write-boundary) end +write-boundary: exit(0) +EOF +pass; diff --git a/src/tests/userprog/write-normal.c b/src/tests/userprog/write-normal.c new file mode 100644 index 0000000..e0297aa --- /dev/null +++ b/src/tests/userprog/write-normal.c @@ -0,0 +1,20 @@ +/* Try writing a file in the most normal way. */ + +#include +#include "tests/userprog/sample.inc" +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + int handle, byte_cnt; + + CHECK (create ("test.txt", sizeof sample - 1), "create \"test.txt\""); + CHECK ((handle = open ("test.txt")) > 1, "open \"test.txt\""); + + byte_cnt = write (handle, sample, sizeof sample - 1); + if (byte_cnt != sizeof sample - 1) + fail ("write() returned %d instead of %zu", byte_cnt, sizeof sample - 1); +} + diff --git a/src/tests/userprog/write-normal.ck b/src/tests/userprog/write-normal.ck new file mode 100644 index 0000000..9fa6024 --- /dev/null +++ b/src/tests/userprog/write-normal.ck @@ -0,0 +1,12 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(write-normal) begin +(write-normal) create "test.txt" +(write-normal) open "test.txt" +(write-normal) end +write-normal: exit(0) +EOF +pass; diff --git a/src/tests/userprog/write-stdin.c b/src/tests/userprog/write-stdin.c new file mode 100644 index 0000000..491ea53 --- /dev/null +++ b/src/tests/userprog/write-stdin.c @@ -0,0 +1,14 @@ +/* Try writing to fd 0 (stdin), + which may just fail or terminate the process with -1 exit + code. */ + +#include +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + char buf = 123; + write (0, &buf, 1); +} diff --git a/src/tests/userprog/write-stdin.ck b/src/tests/userprog/write-stdin.ck new file mode 100644 index 0000000..a6caf81 --- /dev/null +++ b/src/tests/userprog/write-stdin.ck @@ -0,0 +1,13 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF', <<'EOF']); +(write-stdin) begin +(write-stdin) end +write-stdin: exit(0) +EOF +(write-stdin) begin +write-stdin: exit(-1) +EOF +pass; diff --git a/src/tests/userprog/write-zero.c b/src/tests/userprog/write-zero.c new file mode 100644 index 0000000..d8dac9b --- /dev/null +++ b/src/tests/userprog/write-zero.c @@ -0,0 +1,20 @@ +/* Try a 0-byte write, which should return 0 without writing + anything. */ + +#include +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + int handle, byte_cnt; + char buf; + + CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\""); + + buf = 123; + byte_cnt = write (handle, &buf, 0); + if (byte_cnt != 0) + fail("write() returned %d instead of 0", byte_cnt); +} diff --git a/src/tests/userprog/write-zero.ck b/src/tests/userprog/write-zero.ck new file mode 100644 index 0000000..cc4cd60 --- /dev/null +++ b/src/tests/userprog/write-zero.ck @@ -0,0 +1,11 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF']); +(write-zero) begin +(write-zero) open "sample.txt" +(write-zero) end +write-zero: exit(0) +EOF +pass; -- cgit v1.2.1