summaryrefslogtreecommitdiffstats
path: root/pintos-progos/tests/userprog
diff options
context:
space:
mode:
Diffstat (limited to 'pintos-progos/tests/userprog')
-rw-r--r--pintos-progos/tests/userprog/Make.tests133
-rw-r--r--pintos-progos/tests/userprog/Rubric.functionality52
-rw-r--r--pintos-progos/tests/userprog/Rubric.robustness48
-rw-r--r--pintos-progos/tests/userprog/args-dbl-space.ck15
-rw-r--r--pintos-progos/tests/userprog/args-many.ck35
-rw-r--r--pintos-progos/tests/userprog/args-multiple.ck17
-rw-r--r--pintos-progos/tests/userprog/args-none.ck13
-rw-r--r--pintos-progos/tests/userprog/args-single.ck14
-rw-r--r--pintos-progos/tests/userprog/args.c25
-rw-r--r--pintos-progos/tests/userprog/bad-jump.c13
-rw-r--r--pintos-progos/tests/userprog/bad-jump.ck9
-rw-r--r--pintos-progos/tests/userprog/bad-jump2.c13
-rw-r--r--pintos-progos/tests/userprog/bad-jump2.ck9
-rw-r--r--pintos-progos/tests/userprog/bad-read.c13
-rw-r--r--pintos-progos/tests/userprog/bad-read.ck9
-rw-r--r--pintos-progos/tests/userprog/bad-read2.c13
-rw-r--r--pintos-progos/tests/userprog/bad-read2.ck9
-rw-r--r--pintos-progos/tests/userprog/bad-write.c12
-rw-r--r--pintos-progos/tests/userprog/bad-write.ck9
-rw-r--r--pintos-progos/tests/userprog/bad-write2.c12
-rw-r--r--pintos-progos/tests/userprog/bad-write2.ck9
-rw-r--r--pintos-progos/tests/userprog/boundary.c33
-rw-r--r--pintos-progos/tests/userprog/boundary.h7
-rw-r--r--pintos-progos/tests/userprog/child-bad.c14
-rw-r--r--pintos-progos/tests/userprog/child-close.c28
-rw-r--r--pintos-progos/tests/userprog/child-rox.c55
-rw-r--r--pintos-progos/tests/userprog/child-simple.c15
-rw-r--r--pintos-progos/tests/userprog/close-bad-fd.c11
-rw-r--r--pintos-progos/tests/userprog/close-bad-fd.ck13
-rw-r--r--pintos-progos/tests/userprog/close-normal.c14
-rw-r--r--pintos-progos/tests/userprog/close-normal.ck12
-rw-r--r--pintos-progos/tests/userprog/close-stdin.c11
-rw-r--r--pintos-progos/tests/userprog/close-stdin.ck13
-rw-r--r--pintos-progos/tests/userprog/close-stdout.c11
-rw-r--r--pintos-progos/tests/userprog/close-stdout.ck13
-rw-r--r--pintos-progos/tests/userprog/close-twice.c18
-rw-r--r--pintos-progos/tests/userprog/close-twice.ck19
-rw-r--r--pintos-progos/tests/userprog/create-bad-ptr.c12
-rw-r--r--pintos-progos/tests/userprog/create-bad-ptr.ck9
-rw-r--r--pintos-progos/tests/userprog/create-bound.c14
-rw-r--r--pintos-progos/tests/userprog/create-bound.ck11
-rw-r--r--pintos-progos/tests/userprog/create-empty.c10
-rw-r--r--pintos-progos/tests/userprog/create-empty.ck14
-rw-r--r--pintos-progos/tests/userprog/create-exists.c16
-rw-r--r--pintos-progos/tests/userprog/create-exists.ck15
-rw-r--r--pintos-progos/tests/userprog/create-long.c17
-rw-r--r--pintos-progos/tests/userprog/create-long.ck11
-rw-r--r--pintos-progos/tests/userprog/create-normal.c10
-rw-r--r--pintos-progos/tests/userprog/create-normal.ck11
-rw-r--r--pintos-progos/tests/userprog/create-null.c11
-rw-r--r--pintos-progos/tests/userprog/create-null.ck9
-rw-r--r--pintos-progos/tests/userprog/exec-arg.c10
-rw-r--r--pintos-progos/tests/userprog/exec-arg.ck17
-rw-r--r--pintos-progos/tests/userprog/exec-bad-ptr.c11
-rw-r--r--pintos-progos/tests/userprog/exec-bad-ptr.ck13
-rw-r--r--pintos-progos/tests/userprog/exec-missing.c12
-rw-r--r--pintos-progos/tests/userprog/exec-missing.ck31
-rw-r--r--pintos-progos/tests/userprog/exec-multiple.c14
-rw-r--r--pintos-progos/tests/userprog/exec-multiple.ck18
-rw-r--r--pintos-progos/tests/userprog/exec-once.c11
-rw-r--r--pintos-progos/tests/userprog/exec-once.ck12
-rw-r--r--pintos-progos/tests/userprog/exit.c11
-rw-r--r--pintos-progos/tests/userprog/exit.ck9
-rw-r--r--pintos-progos/tests/userprog/halt.c11
-rw-r--r--pintos-progos/tests/userprog/halt.ck15
-rw-r--r--pintos-progos/tests/userprog/lib/.gitignore1
-rw-r--r--pintos-progos/tests/userprog/lib/user/.dummy0
-rw-r--r--pintos-progos/tests/userprog/lib/user/.gitignore1
-rw-r--r--pintos-progos/tests/userprog/multi-child-fd.c25
-rw-r--r--pintos-progos/tests/userprog/multi-child-fd.ck25
-rw-r--r--pintos-progos/tests/userprog/multi-recurse.c34
-rw-r--r--pintos-progos/tests/userprog/multi-recurse.ck70
-rw-r--r--pintos-progos/tests/userprog/no-vm/Make.tests8
-rw-r--r--pintos-progos/tests/userprog/no-vm/Rubric3
-rw-r--r--pintos-progos/tests/userprog/no-vm/multi-oom.c179
-rw-r--r--pintos-progos/tests/userprog/no-vm/multi-oom.ck10
-rw-r--r--pintos-progos/tests/userprog/null.ck8
-rw-r--r--pintos-progos/tests/userprog/open-bad-ptr.c13
-rw-r--r--pintos-progos/tests/userprog/open-bad-ptr.ck13
-rw-r--r--pintos-progos/tests/userprog/open-boundary.c14
-rw-r--r--pintos-progos/tests/userprog/open-boundary.ck11
-rw-r--r--pintos-progos/tests/userprog/open-empty.c13
-rw-r--r--pintos-progos/tests/userprog/open-empty.ck10
-rw-r--r--pintos-progos/tests/userprog/open-missing.c13
-rw-r--r--pintos-progos/tests/userprog/open-missing.ck10
-rw-r--r--pintos-progos/tests/userprog/open-normal.c13
-rw-r--r--pintos-progos/tests/userprog/open-normal.ck10
-rw-r--r--pintos-progos/tests/userprog/open-null.c12
-rw-r--r--pintos-progos/tests/userprog/open-null.ck13
-rw-r--r--pintos-progos/tests/userprog/open-twice.c19
-rw-r--r--pintos-progos/tests/userprog/open-twice.ck12
-rw-r--r--pintos-progos/tests/userprog/read-bad-fd.c21
-rw-r--r--pintos-progos/tests/userprog/read-bad-fd.ck13
-rw-r--r--pintos-progos/tests/userprog/read-bad-ptr.c16
-rw-r--r--pintos-progos/tests/userprog/read-bad-ptr.ck15
-rw-r--r--pintos-progos/tests/userprog/read-boundary.c30
-rw-r--r--pintos-progos/tests/userprog/read-boundary.ck11
-rw-r--r--pintos-progos/tests/userprog/read-normal.c11
-rw-r--r--pintos-progos/tests/userprog/read-normal.ck13
-rw-r--r--pintos-progos/tests/userprog/read-stdout.c14
-rw-r--r--pintos-progos/tests/userprog/read-stdout.ck13
-rw-r--r--pintos-progos/tests/userprog/read-zero.c22
-rw-r--r--pintos-progos/tests/userprog/read-zero.ck11
-rw-r--r--pintos-progos/tests/userprog/rox-child.c5
-rw-r--r--pintos-progos/tests/userprog/rox-child.ck20
-rw-r--r--pintos-progos/tests/userprog/rox-child.inc33
-rw-r--r--pintos-progos/tests/userprog/rox-multichild.c5
-rw-r--r--pintos-progos/tests/userprog/rox-multichild.ck44
-rw-r--r--pintos-progos/tests/userprog/rox-simple.c19
-rw-r--r--pintos-progos/tests/userprog/rox-simple.ck13
-rw-r--r--pintos-progos/tests/userprog/sample.inc6
-rw-r--r--pintos-progos/tests/userprog/sample.txt4
-rw-r--r--pintos-progos/tests/userprog/sc-bad-arg.c17
-rw-r--r--pintos-progos/tests/userprog/sc-bad-arg.ck9
-rw-r--r--pintos-progos/tests/userprog/sc-bad-sp.c20
-rw-r--r--pintos-progos/tests/userprog/sc-bad-sp.ck9
-rw-r--r--pintos-progos/tests/userprog/sc-boundary-2.c22
-rw-r--r--pintos-progos/tests/userprog/sc-boundary-2.ck9
-rw-r--r--pintos-progos/tests/userprog/sc-boundary.c22
-rw-r--r--pintos-progos/tests/userprog/sc-boundary.ck9
-rw-r--r--pintos-progos/tests/userprog/wait-bad-pid.c11
-rw-r--r--pintos-progos/tests/userprog/wait-bad-pid.ck13
-rw-r--r--pintos-progos/tests/userprog/wait-killed.c11
-rw-r--r--pintos-progos/tests/userprog/wait-killed.ck13
-rw-r--r--pintos-progos/tests/userprog/wait-simple.c11
-rw-r--r--pintos-progos/tests/userprog/wait-simple.ck13
-rw-r--r--pintos-progos/tests/userprog/wait-twice.c15
-rw-r--r--pintos-progos/tests/userprog/wait-twice.ck14
-rw-r--r--pintos-progos/tests/userprog/write-bad-fd.c20
-rw-r--r--pintos-progos/tests/userprog/write-bad-fd.ck13
-rw-r--r--pintos-progos/tests/userprog/write-bad-ptr.c16
-rw-r--r--pintos-progos/tests/userprog/write-bad-ptr.ck15
-rw-r--r--pintos-progos/tests/userprog/write-boundary.c25
-rw-r--r--pintos-progos/tests/userprog/write-boundary.ck11
-rw-r--r--pintos-progos/tests/userprog/write-normal.c20
-rw-r--r--pintos-progos/tests/userprog/write-normal.ck12
-rw-r--r--pintos-progos/tests/userprog/write-stdin.c14
-rw-r--r--pintos-progos/tests/userprog/write-stdin.ck13
-rw-r--r--pintos-progos/tests/userprog/write-zero.c20
-rw-r--r--pintos-progos/tests/userprog/write-zero.ck11
140 files changed, 2421 insertions, 0 deletions
diff --git a/pintos-progos/tests/userprog/Make.tests b/pintos-progos/tests/userprog/Make.tests
new file mode 100644
index 0000000..88b0737
--- /dev/null
+++ b/pintos-progos/tests/userprog/Make.tests
@@ -0,0 +1,133 @@
1# -*- makefile -*-
2
3tests/%.output: FILESYSSOURCE = --filesys-size=2
4tests/%.output: PUTFILES = $(filter-out kernel.bin loader.bin, $^)
5
6tests/userprog_TESTS = $(addprefix tests/userprog/,args-none \
7args-single args-multiple args-many args-dbl-space sc-bad-sp \
8sc-bad-arg sc-boundary sc-boundary-2 halt exit create-normal \
9create-empty create-null create-bad-ptr create-long create-exists \
10create-bound open-normal open-missing open-boundary open-empty \
11open-null open-bad-ptr open-twice close-normal close-twice close-stdin \
12close-stdout close-bad-fd read-normal read-bad-ptr read-boundary \
13read-zero read-stdout read-bad-fd write-normal write-bad-ptr \
14write-boundary write-zero write-stdin write-bad-fd exec-once exec-arg \
15exec-multiple exec-missing exec-bad-ptr wait-simple wait-twice \
16wait-killed wait-bad-pid multi-recurse multi-child-fd rox-simple \
17rox-child rox-multichild bad-read bad-write bad-read2 bad-write2 \
18bad-jump bad-jump2)
19
20tests/userprog_PROGS = $(tests/userprog_TESTS) $(addprefix \
21tests/userprog/,child-simple child-args child-bad child-close child-rox)
22
23tests/userprog/args-none_SRC = tests/userprog/args.c
24tests/userprog/args-single_SRC = tests/userprog/args.c
25tests/userprog/args-multiple_SRC = tests/userprog/args.c
26tests/userprog/args-many_SRC = tests/userprog/args.c
27tests/userprog/args-dbl-space_SRC = tests/userprog/args.c
28tests/userprog/sc-bad-sp_SRC = tests/userprog/sc-bad-sp.c tests/main.c
29tests/userprog/sc-bad-arg_SRC = tests/userprog/sc-bad-arg.c tests/main.c
30tests/userprog/bad-read_SRC = tests/userprog/bad-read.c tests/main.c
31tests/userprog/bad-write_SRC = tests/userprog/bad-write.c tests/main.c
32tests/userprog/bad-jump_SRC = tests/userprog/bad-jump.c tests/main.c
33tests/userprog/bad-read2_SRC = tests/userprog/bad-read2.c tests/main.c
34tests/userprog/bad-write2_SRC = tests/userprog/bad-write2.c tests/main.c
35tests/userprog/bad-jump2_SRC = tests/userprog/bad-jump2.c tests/main.c
36tests/userprog/sc-boundary_SRC = tests/userprog/sc-boundary.c \
37tests/userprog/boundary.c tests/main.c
38tests/userprog/sc-boundary-2_SRC = tests/userprog/sc-boundary-2.c \
39tests/userprog/boundary.c tests/main.c
40tests/userprog/halt_SRC = tests/userprog/halt.c tests/main.c
41tests/userprog/exit_SRC = tests/userprog/exit.c tests/main.c
42tests/userprog/create-normal_SRC = tests/userprog/create-normal.c tests/main.c
43tests/userprog/create-empty_SRC = tests/userprog/create-empty.c tests/main.c
44tests/userprog/create-null_SRC = tests/userprog/create-null.c tests/main.c
45tests/userprog/create-bad-ptr_SRC = tests/userprog/create-bad-ptr.c \
46tests/main.c
47tests/userprog/create-long_SRC = tests/userprog/create-long.c tests/main.c
48tests/userprog/create-exists_SRC = tests/userprog/create-exists.c tests/main.c
49tests/userprog/create-bound_SRC = tests/userprog/create-bound.c \
50tests/userprog/boundary.c tests/main.c
51tests/userprog/open-normal_SRC = tests/userprog/open-normal.c tests/main.c
52tests/userprog/open-missing_SRC = tests/userprog/open-missing.c tests/main.c
53tests/userprog/open-boundary_SRC = tests/userprog/open-boundary.c \
54tests/userprog/boundary.c tests/main.c
55tests/userprog/open-empty_SRC = tests/userprog/open-empty.c tests/main.c
56tests/userprog/open-null_SRC = tests/userprog/open-null.c tests/main.c
57tests/userprog/open-bad-ptr_SRC = tests/userprog/open-bad-ptr.c tests/main.c
58tests/userprog/open-twice_SRC = tests/userprog/open-twice.c tests/main.c
59tests/userprog/close-normal_SRC = tests/userprog/close-normal.c tests/main.c
60tests/userprog/close-twice_SRC = tests/userprog/close-twice.c tests/main.c
61tests/userprog/close-stdin_SRC = tests/userprog/close-stdin.c tests/main.c
62tests/userprog/close-stdout_SRC = tests/userprog/close-stdout.c tests/main.c
63tests/userprog/close-bad-fd_SRC = tests/userprog/close-bad-fd.c tests/main.c
64tests/userprog/read-normal_SRC = tests/userprog/read-normal.c tests/main.c
65tests/userprog/read-bad-ptr_SRC = tests/userprog/read-bad-ptr.c tests/main.c
66tests/userprog/read-boundary_SRC = tests/userprog/read-boundary.c \
67tests/userprog/boundary.c tests/main.c
68tests/userprog/read-zero_SRC = tests/userprog/read-zero.c tests/main.c
69tests/userprog/read-stdout_SRC = tests/userprog/read-stdout.c tests/main.c
70tests/userprog/read-bad-fd_SRC = tests/userprog/read-bad-fd.c tests/main.c
71tests/userprog/write-normal_SRC = tests/userprog/write-normal.c tests/main.c
72tests/userprog/write-bad-ptr_SRC = tests/userprog/write-bad-ptr.c tests/main.c
73tests/userprog/write-boundary_SRC = tests/userprog/write-boundary.c \
74tests/userprog/boundary.c tests/main.c
75tests/userprog/write-zero_SRC = tests/userprog/write-zero.c tests/main.c
76tests/userprog/write-stdin_SRC = tests/userprog/write-stdin.c tests/main.c
77tests/userprog/write-bad-fd_SRC = tests/userprog/write-bad-fd.c tests/main.c
78tests/userprog/exec-once_SRC = tests/userprog/exec-once.c tests/main.c
79tests/userprog/exec-arg_SRC = tests/userprog/exec-arg.c tests/main.c
80tests/userprog/exec-multiple_SRC = tests/userprog/exec-multiple.c tests/main.c
81tests/userprog/exec-missing_SRC = tests/userprog/exec-missing.c tests/main.c
82tests/userprog/exec-bad-ptr_SRC = tests/userprog/exec-bad-ptr.c tests/main.c
83tests/userprog/wait-simple_SRC = tests/userprog/wait-simple.c tests/main.c
84tests/userprog/wait-twice_SRC = tests/userprog/wait-twice.c tests/main.c
85tests/userprog/wait-killed_SRC = tests/userprog/wait-killed.c tests/main.c
86tests/userprog/wait-bad-pid_SRC = tests/userprog/wait-bad-pid.c tests/main.c
87tests/userprog/multi-recurse_SRC = tests/userprog/multi-recurse.c
88tests/userprog/multi-child-fd_SRC = tests/userprog/multi-child-fd.c \
89tests/main.c
90tests/userprog/rox-simple_SRC = tests/userprog/rox-simple.c tests/main.c
91tests/userprog/rox-child_SRC = tests/userprog/rox-child.c tests/main.c
92tests/userprog/rox-multichild_SRC = tests/userprog/rox-multichild.c \
93tests/main.c
94
95tests/userprog/child-simple_SRC = tests/userprog/child-simple.c
96tests/userprog/child-args_SRC = tests/userprog/args.c
97tests/userprog/child-bad_SRC = tests/userprog/child-bad.c tests/main.c
98tests/userprog/child-close_SRC = tests/userprog/child-close.c
99tests/userprog/child-rox_SRC = tests/userprog/child-rox.c
100
101$(foreach prog,$(tests/userprog_PROGS),$(eval $(prog)_SRC += tests/lib.c))
102
103tests/userprog/args-single_ARGS = onearg
104tests/userprog/args-multiple_ARGS = some arguments for you!
105tests/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
106tests/userprog/args-dbl-space_ARGS = two spaces!
107tests/userprog/multi-recurse_ARGS = 15
108
109tests/userprog/open-normal_PUTFILES += tests/userprog/sample.txt
110tests/userprog/open-boundary_PUTFILES += tests/userprog/sample.txt
111tests/userprog/open-twice_PUTFILES += tests/userprog/sample.txt
112tests/userprog/close-normal_PUTFILES += tests/userprog/sample.txt
113tests/userprog/close-twice_PUTFILES += tests/userprog/sample.txt
114tests/userprog/read-normal_PUTFILES += tests/userprog/sample.txt
115tests/userprog/read-bad-ptr_PUTFILES += tests/userprog/sample.txt
116tests/userprog/read-boundary_PUTFILES += tests/userprog/sample.txt
117tests/userprog/read-zero_PUTFILES += tests/userprog/sample.txt
118tests/userprog/write-normal_PUTFILES += tests/userprog/sample.txt
119tests/userprog/write-bad-ptr_PUTFILES += tests/userprog/sample.txt
120tests/userprog/write-boundary_PUTFILES += tests/userprog/sample.txt
121tests/userprog/write-zero_PUTFILES += tests/userprog/sample.txt
122tests/userprog/multi-child-fd_PUTFILES += tests/userprog/sample.txt
123
124tests/userprog/exec-once_PUTFILES += tests/userprog/child-simple
125tests/userprog/exec-multiple_PUTFILES += tests/userprog/child-simple
126tests/userprog/wait-simple_PUTFILES += tests/userprog/child-simple
127tests/userprog/wait-twice_PUTFILES += tests/userprog/child-simple
128
129tests/userprog/exec-arg_PUTFILES += tests/userprog/child-args
130tests/userprog/multi-child-fd_PUTFILES += tests/userprog/child-close
131tests/userprog/wait-killed_PUTFILES += tests/userprog/child-bad
132tests/userprog/rox-child_PUTFILES += tests/userprog/child-rox
133tests/userprog/rox-multichild_PUTFILES += tests/userprog/child-rox
diff --git a/pintos-progos/tests/userprog/Rubric.functionality b/pintos-progos/tests/userprog/Rubric.functionality
new file mode 100644
index 0000000..ea76c44
--- /dev/null
+++ b/pintos-progos/tests/userprog/Rubric.functionality
@@ -0,0 +1,52 @@
1Functionality of system calls:
2- Test argument passing on Pintos command line.
33 args-none
43 args-single
53 args-multiple
63 args-many
73 args-dbl-space
8
9- Test "create" system call.
103 create-empty
113 create-long
123 create-normal
133 create-exists
14
15- Test "open" system call.
163 open-missing
173 open-normal
183 open-twice
19
20- Test "read" system call.
213 read-normal
223 read-zero
23
24- Test "write" system call.
253 write-normal
263 write-zero
27
28- Test "close" system call.
293 close-normal
30
31- Test "exec" system call.
325 exec-once
335 exec-multiple
345 exec-arg
35
36- Test "wait" system call.
375 wait-simple
385 wait-twice
39
40- Test "exit" system call.
415 exit
42
43- Test "halt" system call.
443 halt
45
46- Test recursive execution of user programs.
4715 multi-recurse
48
49- Test read-only executable feature.
503 rox-simple
513 rox-child
523 rox-multichild
diff --git a/pintos-progos/tests/userprog/Rubric.robustness b/pintos-progos/tests/userprog/Rubric.robustness
new file mode 100644
index 0000000..b7d1035
--- /dev/null
+++ b/pintos-progos/tests/userprog/Rubric.robustness
@@ -0,0 +1,48 @@
1Robustness of system calls:
2- Test robustness of file descriptor handling.
32 close-stdin
42 close-stdout
52 close-bad-fd
62 close-twice
72 read-bad-fd
82 read-stdout
92 write-bad-fd
102 write-stdin
112 multi-child-fd
12
13- Test robustness of pointer handling.
143 create-bad-ptr
153 exec-bad-ptr
163 open-bad-ptr
173 read-bad-ptr
183 write-bad-ptr
19
20- Test robustness of buffer copying across page boundaries.
213 create-bound
223 open-boundary
233 read-boundary
243 write-boundary
25
26- Test handling of null pointer and empty strings.
272 create-null
282 open-null
292 open-empty
30
31- Test robustness of system call implementation.
323 sc-bad-arg
333 sc-bad-sp
345 sc-boundary
355 sc-boundary-2
36
37- Test robustness of "exec" and "wait" system calls.
385 exec-missing
395 wait-bad-pid
405 wait-killed
41
42- Test robustness of exception handling.
431 bad-read
441 bad-write
451 bad-jump
461 bad-read2
471 bad-write2
481 bad-jump2
diff --git a/pintos-progos/tests/userprog/args-dbl-space.ck b/pintos-progos/tests/userprog/args-dbl-space.ck
new file mode 100644
index 0000000..dfbcf4b
--- /dev/null
+++ b/pintos-progos/tests/userprog/args-dbl-space.ck
@@ -0,0 +1,15 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(args) begin
7(args) argc = 3
8(args) argv[0] = 'args-dbl-space'
9(args) argv[1] = 'two'
10(args) argv[2] = 'spaces!'
11(args) argv[3] = null
12(args) end
13args-dbl-space: exit(0)
14EOF
15pass;
diff --git a/pintos-progos/tests/userprog/args-many.ck b/pintos-progos/tests/userprog/args-many.ck
new file mode 100644
index 0000000..214574a
--- /dev/null
+++ b/pintos-progos/tests/userprog/args-many.ck
@@ -0,0 +1,35 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(args) begin
7(args) argc = 23
8(args) argv[0] = 'args-many'
9(args) argv[1] = 'a'
10(args) argv[2] = 'b'
11(args) argv[3] = 'c'
12(args) argv[4] = 'd'
13(args) argv[5] = 'e'
14(args) argv[6] = 'f'
15(args) argv[7] = 'g'
16(args) argv[8] = 'h'
17(args) argv[9] = 'i'
18(args) argv[10] = 'j'
19(args) argv[11] = 'k'
20(args) argv[12] = 'l'
21(args) argv[13] = 'm'
22(args) argv[14] = 'n'
23(args) argv[15] = 'o'
24(args) argv[16] = 'p'
25(args) argv[17] = 'q'
26(args) argv[18] = 'r'
27(args) argv[19] = 's'
28(args) argv[20] = 't'
29(args) argv[21] = 'u'
30(args) argv[22] = 'v'
31(args) argv[23] = null
32(args) end
33args-many: exit(0)
34EOF
35pass;
diff --git a/pintos-progos/tests/userprog/args-multiple.ck b/pintos-progos/tests/userprog/args-multiple.ck
new file mode 100644
index 0000000..227e6cc
--- /dev/null
+++ b/pintos-progos/tests/userprog/args-multiple.ck
@@ -0,0 +1,17 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(args) begin
7(args) argc = 5
8(args) argv[0] = 'args-multiple'
9(args) argv[1] = 'some'
10(args) argv[2] = 'arguments'
11(args) argv[3] = 'for'
12(args) argv[4] = 'you!'
13(args) argv[5] = null
14(args) end
15args-multiple: exit(0)
16EOF
17pass;
diff --git a/pintos-progos/tests/userprog/args-none.ck b/pintos-progos/tests/userprog/args-none.ck
new file mode 100644
index 0000000..146318e
--- /dev/null
+++ b/pintos-progos/tests/userprog/args-none.ck
@@ -0,0 +1,13 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(args) begin
7(args) argc = 1
8(args) argv[0] = 'args-none'
9(args) argv[1] = null
10(args) end
11args-none: exit(0)
12EOF
13pass;
diff --git a/pintos-progos/tests/userprog/args-single.ck b/pintos-progos/tests/userprog/args-single.ck
new file mode 100644
index 0000000..24582b4
--- /dev/null
+++ b/pintos-progos/tests/userprog/args-single.ck
@@ -0,0 +1,14 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(args) begin
7(args) argc = 2
8(args) argv[0] = 'args-single'
9(args) argv[1] = 'onearg'
10(args) argv[2] = null
11(args) end
12args-single: exit(0)
13EOF
14pass;
diff --git a/pintos-progos/tests/userprog/args.c b/pintos-progos/tests/userprog/args.c
new file mode 100644
index 0000000..20eda44
--- /dev/null
+++ b/pintos-progos/tests/userprog/args.c
@@ -0,0 +1,25 @@
1/* Prints the command-line arguments.
2 This program is used for all of the args-* tests. Grading is
3 done differently for each of the args-* tests based on the
4 output. */
5
6#include "tests/lib.h"
7
8int
9main (int argc, char *argv[])
10{
11 int i;
12
13 test_name = "args";
14
15 msg ("begin");
16 msg ("argc = %d", argc);
17 for (i = 0; i <= argc; i++)
18 if (argv[i] != NULL)
19 msg ("argv[%d] = '%s'", i, argv[i]);
20 else
21 msg ("argv[%d] = null", i);
22 msg ("end");
23
24 return 0;
25}
diff --git a/pintos-progos/tests/userprog/bad-jump.c b/pintos-progos/tests/userprog/bad-jump.c
new file mode 100644
index 0000000..51b7c9f
--- /dev/null
+++ b/pintos-progos/tests/userprog/bad-jump.c
@@ -0,0 +1,13 @@
1/* This program attempts to execute code at address 0, which is not mapped.
2 This should terminate the process with a -1 exit code. */
3
4#include "tests/lib.h"
5#include "tests/main.h"
6
7void
8test_main (void)
9{
10 msg ("Congratulations - you have successfully called NULL: %d",
11 ((int (*)(void))NULL)());
12 fail ("should have exited with -1");
13}
diff --git a/pintos-progos/tests/userprog/bad-jump.ck b/pintos-progos/tests/userprog/bad-jump.ck
new file mode 100644
index 0000000..e1c178b
--- /dev/null
+++ b/pintos-progos/tests/userprog/bad-jump.ck
@@ -0,0 +1,9 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']);
6(bad-jump) begin
7bad-jump: exit(-1)
8EOF
9pass;
diff --git a/pintos-progos/tests/userprog/bad-jump2.c b/pintos-progos/tests/userprog/bad-jump2.c
new file mode 100644
index 0000000..dc7c2a7
--- /dev/null
+++ b/pintos-progos/tests/userprog/bad-jump2.c
@@ -0,0 +1,13 @@
1/* This program attempts to execute code at a kernel virtual address.
2 This should terminate the process with a -1 exit code. */
3
4#include "tests/lib.h"
5#include "tests/main.h"
6
7void
8test_main (void)
9{
10 msg ("Congratulations - you have successfully called kernel code: %d",
11 ((int (*)(void))0xC0000000)());
12 fail ("should have exited with -1");
13}
diff --git a/pintos-progos/tests/userprog/bad-jump2.ck b/pintos-progos/tests/userprog/bad-jump2.ck
new file mode 100644
index 0000000..35f0f97
--- /dev/null
+++ b/pintos-progos/tests/userprog/bad-jump2.ck
@@ -0,0 +1,9 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']);
6(bad-jump2) begin
7bad-jump2: exit(-1)
8EOF
9pass;
diff --git a/pintos-progos/tests/userprog/bad-read.c b/pintos-progos/tests/userprog/bad-read.c
new file mode 100644
index 0000000..904c278
--- /dev/null
+++ b/pintos-progos/tests/userprog/bad-read.c
@@ -0,0 +1,13 @@
1/* This program attempts to read memory at an address that is not mapped.
2 This should terminate the process with a -1 exit code. */
3
4#include "tests/lib.h"
5#include "tests/main.h"
6
7void
8test_main (void)
9{
10 msg ("Congratulations - you have successfully dereferenced NULL: %d",
11 *(int *)NULL);
12 fail ("should have exited with -1");
13}
diff --git a/pintos-progos/tests/userprog/bad-read.ck b/pintos-progos/tests/userprog/bad-read.ck
new file mode 100644
index 0000000..4d4d926
--- /dev/null
+++ b/pintos-progos/tests/userprog/bad-read.ck
@@ -0,0 +1,9 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']);
6(bad-read) begin
7bad-read: exit(-1)
8EOF
9pass;
diff --git a/pintos-progos/tests/userprog/bad-read2.c b/pintos-progos/tests/userprog/bad-read2.c
new file mode 100644
index 0000000..a2fc237
--- /dev/null
+++ b/pintos-progos/tests/userprog/bad-read2.c
@@ -0,0 +1,13 @@
1/* This program attempts to read kernel memory.
2 This should terminate the process with a -1 exit code. */
3
4#include "tests/lib.h"
5#include "tests/main.h"
6
7void
8test_main (void)
9{
10 msg ("Congratulations - you have successfully read kernel memory: %d",
11 *(int *)0xC0000000);
12 fail ("should have exited with -1");
13}
diff --git a/pintos-progos/tests/userprog/bad-read2.ck b/pintos-progos/tests/userprog/bad-read2.ck
new file mode 100644
index 0000000..fa27c7d
--- /dev/null
+++ b/pintos-progos/tests/userprog/bad-read2.ck
@@ -0,0 +1,9 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']);
6(bad-read2) begin
7bad-read2: exit(-1)
8EOF
9pass;
diff --git a/pintos-progos/tests/userprog/bad-write.c b/pintos-progos/tests/userprog/bad-write.c
new file mode 100644
index 0000000..000c26b
--- /dev/null
+++ b/pintos-progos/tests/userprog/bad-write.c
@@ -0,0 +1,12 @@
1/* This program attempts to write to memory at an address that is not mapped.
2 This should terminate the process with a -1 exit code. */
3
4#include "tests/lib.h"
5#include "tests/main.h"
6
7void
8test_main (void)
9{
10 *(int *)NULL = 42;
11 fail ("should have exited with -1");
12}
diff --git a/pintos-progos/tests/userprog/bad-write.ck b/pintos-progos/tests/userprog/bad-write.ck
new file mode 100644
index 0000000..d213b49
--- /dev/null
+++ b/pintos-progos/tests/userprog/bad-write.ck
@@ -0,0 +1,9 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']);
6(bad-write) begin
7bad-write: exit(-1)
8EOF
9pass;
diff --git a/pintos-progos/tests/userprog/bad-write2.c b/pintos-progos/tests/userprog/bad-write2.c
new file mode 100644
index 0000000..753da1e
--- /dev/null
+++ b/pintos-progos/tests/userprog/bad-write2.c
@@ -0,0 +1,12 @@
1/* This program attempts to write to kernel memory.
2 This should terminate the process with a -1 exit code. */
3
4#include "tests/lib.h"
5#include "tests/main.h"
6
7void
8test_main (void)
9{
10 *(int *)0xC0000000 = 42;
11 fail ("should have exited with -1");
12}
diff --git a/pintos-progos/tests/userprog/bad-write2.ck b/pintos-progos/tests/userprog/bad-write2.ck
new file mode 100644
index 0000000..c6a3420
--- /dev/null
+++ b/pintos-progos/tests/userprog/bad-write2.ck
@@ -0,0 +1,9 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']);
6(bad-write2) begin
7bad-write2: exit(-1)
8EOF
9pass;
diff --git a/pintos-progos/tests/userprog/boundary.c b/pintos-progos/tests/userprog/boundary.c
new file mode 100644
index 0000000..59907ec
--- /dev/null
+++ b/pintos-progos/tests/userprog/boundary.c
@@ -0,0 +1,33 @@
1/* Utility function for tests that try to break system calls by
2 passing them data that crosses from one virtual page to
3 another. */
4
5#include <inttypes.h>
6#include <round.h>
7#include <string.h>
8#include "tests/userprog/boundary.h"
9
10static char dst[8192];
11
12/* Returns the beginning of a page. There are at least 2048
13 modifiable bytes on either side of the pointer returned. */
14void *
15get_boundary_area (void)
16{
17 char *p = (char *) ROUND_UP ((uintptr_t) dst, 4096);
18 if (p - dst < 2048)
19 p += 4096;
20 return p;
21}
22
23/* Returns a copy of SRC split across the boundary between two
24 pages. */
25char *
26copy_string_across_boundary (const char *src)
27{
28 char *p = get_boundary_area ();
29 p -= strlen (src) < 4096 ? strlen (src) / 2 : 4096;
30 strlcpy (p, src, 4096);
31 return p;
32}
33
diff --git a/pintos-progos/tests/userprog/boundary.h b/pintos-progos/tests/userprog/boundary.h
new file mode 100644
index 0000000..c8e4b3b
--- /dev/null
+++ b/pintos-progos/tests/userprog/boundary.h
@@ -0,0 +1,7 @@
1#ifndef TESTS_USERPROG_BOUNDARY_H
2#define TESTS_USERPROG_BOUNDARY_H
3
4void *get_boundary_area (void);
5char *copy_string_across_boundary (const char *);
6
7#endif /* tests/userprog/boundary.h */
diff --git a/pintos-progos/tests/userprog/child-bad.c b/pintos-progos/tests/userprog/child-bad.c
new file mode 100644
index 0000000..77d7a69
--- /dev/null
+++ b/pintos-progos/tests/userprog/child-bad.c
@@ -0,0 +1,14 @@
1/* Child process run by wait-killed test.
2 Sets the stack pointer (%esp) to an invalid value and invokes
3 a system call, which should then terminate the process with a
4 -1 exit code. */
5
6#include "tests/lib.h"
7#include "tests/main.h"
8
9void
10test_main (void)
11{
12 asm volatile ("movl $0x20101234, %esp; int $0x30");
13 fail ("should have exited with -1");
14}
diff --git a/pintos-progos/tests/userprog/child-close.c b/pintos-progos/tests/userprog/child-close.c
new file mode 100644
index 0000000..ac948c8
--- /dev/null
+++ b/pintos-progos/tests/userprog/child-close.c
@@ -0,0 +1,28 @@
1/* Child process run by multi-child-fd test.
2
3 Attempts to close the file descriptor passed as the first
4 command-line argument. This is invalid, because file
5 descriptors are not inherited in Pintos. Two results are
6 allowed: either the system call should return without taking
7 any action, or the kernel should terminate the process with a
8 -1 exit code. */
9
10#include <ctype.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <syscall.h>
14#include "tests/lib.h"
15
16const char *test_name = "child-close";
17
18int
19main (int argc UNUSED, char *argv[])
20{
21 msg ("begin");
22 if (!isdigit (*argv[1]))
23 fail ("bad command-line arguments");
24 close (atoi (argv[1]));
25 msg ("end");
26
27 return 0;
28}
diff --git a/pintos-progos/tests/userprog/child-rox.c b/pintos-progos/tests/userprog/child-rox.c
new file mode 100644
index 0000000..aba808b
--- /dev/null
+++ b/pintos-progos/tests/userprog/child-rox.c
@@ -0,0 +1,55 @@
1/* Child process run by rox-child and rox-multichild tests.
2 Opens and tries to write to its own executable, verifying that
3 that is disallowed.
4 Then recursively executes itself to the depth indicated by the
5 first command-line argument. */
6
7#include <ctype.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <syscall.h>
11#include "tests/lib.h"
12
13const char *test_name = "child-rox";
14
15static void
16try_write (void)
17{
18 int handle;
19 char buffer[19];
20
21 quiet = true;
22 CHECK ((handle = open ("child-rox")) > 1, "open \"child-rox\"");
23 quiet = false;
24
25 CHECK (write (handle, buffer, sizeof buffer) == 0,
26 "try to write \"child-rox\"");
27
28 close (handle);
29}
30
31int
32main (int argc UNUSED, char *argv[])
33{
34 msg ("begin");
35 try_write ();
36
37 if (!isdigit (*argv[1]))
38 fail ("bad command-line arguments");
39 if (atoi (argv[1]) > 1)
40 {
41 char cmd[128];
42 int child;
43
44 snprintf (cmd, sizeof cmd, "child-rox %d", atoi (argv[1]) - 1);
45 CHECK ((child = exec (cmd)) != -1, "exec \"%s\"", cmd);
46 quiet = true;
47 CHECK (wait (child) == 12, "wait for \"child-rox\"");
48 quiet = false;
49 }
50
51 try_write ();
52 msg ("end");
53
54 return 12;
55}
diff --git a/pintos-progos/tests/userprog/child-simple.c b/pintos-progos/tests/userprog/child-simple.c
new file mode 100644
index 0000000..0d2dacf
--- /dev/null
+++ b/pintos-progos/tests/userprog/child-simple.c
@@ -0,0 +1,15 @@
1/* Child process run by exec-multiple, exec-one, wait-simple, and
2 wait-twice tests.
3 Just prints a single message and terminates. */
4
5#include <stdio.h>
6#include "tests/lib.h"
7
8const char *test_name = "child-simple";
9
10int
11main (void)
12{
13 msg ("run");
14 return 81;
15}
diff --git a/pintos-progos/tests/userprog/close-bad-fd.c b/pintos-progos/tests/userprog/close-bad-fd.c
new file mode 100644
index 0000000..f63bb9a
--- /dev/null
+++ b/pintos-progos/tests/userprog/close-bad-fd.c
@@ -0,0 +1,11 @@
1/* Tries to close an invalid fd, which must either fail silently
2 or terminate with exit code -1. */
3
4#include <syscall.h>
5#include "tests/main.h"
6
7void
8test_main (void)
9{
10 close (0x20101234);
11}
diff --git a/pintos-progos/tests/userprog/close-bad-fd.ck b/pintos-progos/tests/userprog/close-bad-fd.ck
new file mode 100644
index 0000000..497b17c
--- /dev/null
+++ b/pintos-progos/tests/userprog/close-bad-fd.ck
@@ -0,0 +1,13 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF', <<'EOF']);
6(close-bad-fd) begin
7(close-bad-fd) end
8close-bad-fd: exit(0)
9EOF
10(close-bad-fd) begin
11close-bad-fd: exit(-1)
12EOF
13pass;
diff --git a/pintos-progos/tests/userprog/close-normal.c b/pintos-progos/tests/userprog/close-normal.c
new file mode 100644
index 0000000..8ce04e3
--- /dev/null
+++ b/pintos-progos/tests/userprog/close-normal.c
@@ -0,0 +1,14 @@
1/* Opens a file and then closes it. */
2
3#include <syscall.h>
4#include "tests/lib.h"
5#include "tests/main.h"
6
7void
8test_main (void)
9{
10 int handle;
11 CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
12 msg ("close \"sample.txt\"");
13 close (handle);
14}
diff --git a/pintos-progos/tests/userprog/close-normal.ck b/pintos-progos/tests/userprog/close-normal.ck
new file mode 100644
index 0000000..fe41342
--- /dev/null
+++ b/pintos-progos/tests/userprog/close-normal.ck
@@ -0,0 +1,12 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(close-normal) begin
7(close-normal) open "sample.txt"
8(close-normal) close "sample.txt"
9(close-normal) end
10close-normal: exit(0)
11EOF
12pass;
diff --git a/pintos-progos/tests/userprog/close-stdin.c b/pintos-progos/tests/userprog/close-stdin.c
new file mode 100644
index 0000000..9bbf9f2
--- /dev/null
+++ b/pintos-progos/tests/userprog/close-stdin.c
@@ -0,0 +1,11 @@
1/* Tries to close the keyboard input stream, which must either
2 fail silently or terminate with exit code -1. */
3
4#include <syscall.h>
5#include "tests/main.h"
6
7void
8test_main (void)
9{
10 close (0);
11}
diff --git a/pintos-progos/tests/userprog/close-stdin.ck b/pintos-progos/tests/userprog/close-stdin.ck
new file mode 100644
index 0000000..3d28507
--- /dev/null
+++ b/pintos-progos/tests/userprog/close-stdin.ck
@@ -0,0 +1,13 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF', <<'EOF']);
6(close-stdin) begin
7(close-stdin) end
8close-stdin: exit(0)
9EOF
10(close-stdin) begin
11close-stdin: exit(-1)
12EOF
13pass;
diff --git a/pintos-progos/tests/userprog/close-stdout.c b/pintos-progos/tests/userprog/close-stdout.c
new file mode 100644
index 0000000..886523f
--- /dev/null
+++ b/pintos-progos/tests/userprog/close-stdout.c
@@ -0,0 +1,11 @@
1/* Tries to close the console output stream, which must either
2 fail silently or terminate with exit code -1. */
3
4#include <syscall.h>
5#include "tests/main.h"
6
7void
8test_main (void)
9{
10 close (1);
11}
diff --git a/pintos-progos/tests/userprog/close-stdout.ck b/pintos-progos/tests/userprog/close-stdout.ck
new file mode 100644
index 0000000..3cbbcff
--- /dev/null
+++ b/pintos-progos/tests/userprog/close-stdout.ck
@@ -0,0 +1,13 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF', <<'EOF']);
6(close-stdout) begin
7(close-stdout) end
8close-stdout: exit(0)
9EOF
10(close-stdout) begin
11close-stdout: exit(-1)
12EOF
13pass;
diff --git a/pintos-progos/tests/userprog/close-twice.c b/pintos-progos/tests/userprog/close-twice.c
new file mode 100644
index 0000000..830bccf
--- /dev/null
+++ b/pintos-progos/tests/userprog/close-twice.c
@@ -0,0 +1,18 @@
1/* Opens a file and then tries to close it twice. The second
2 close must either fail silently or terminate with exit code
3 -1. */
4
5#include <syscall.h>
6#include "tests/lib.h"
7#include "tests/main.h"
8
9void
10test_main (void)
11{
12 int handle;
13 CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
14 msg ("close \"sample.txt\"");
15 close (handle);
16 msg ("close \"sample.txt\" again");
17 close (handle);
18}
diff --git a/pintos-progos/tests/userprog/close-twice.ck b/pintos-progos/tests/userprog/close-twice.ck
new file mode 100644
index 0000000..deb55a6
--- /dev/null
+++ b/pintos-progos/tests/userprog/close-twice.ck
@@ -0,0 +1,19 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF', <<'EOF']);
6(close-twice) begin
7(close-twice) open "sample.txt"
8(close-twice) close "sample.txt"
9(close-twice) close "sample.txt" again
10(close-twice) end
11close-twice: exit(0)
12EOF
13(close-twice) begin
14(close-twice) open "sample.txt"
15(close-twice) close "sample.txt"
16(close-twice) close "sample.txt" again
17close-twice: exit(-1)
18EOF
19pass;
diff --git a/pintos-progos/tests/userprog/create-bad-ptr.c b/pintos-progos/tests/userprog/create-bad-ptr.c
new file mode 100644
index 0000000..4a07bb3
--- /dev/null
+++ b/pintos-progos/tests/userprog/create-bad-ptr.c
@@ -0,0 +1,12 @@
1/* Passes a bad pointer to the create system call,
2 which must cause the process to be terminated with exit code
3 -1. */
4
5#include "tests/lib.h"
6#include "tests/main.h"
7
8void
9test_main (void)
10{
11 msg ("create(0x20101234): %d", create ((char *) 0x20101234, 0));
12}
diff --git a/pintos-progos/tests/userprog/create-bad-ptr.ck b/pintos-progos/tests/userprog/create-bad-ptr.ck
new file mode 100644
index 0000000..ac13405
--- /dev/null
+++ b/pintos-progos/tests/userprog/create-bad-ptr.ck
@@ -0,0 +1,9 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(create-bad-ptr) begin
7create-bad-ptr: exit(-1)
8EOF
9pass;
diff --git a/pintos-progos/tests/userprog/create-bound.c b/pintos-progos/tests/userprog/create-bound.c
new file mode 100644
index 0000000..0a829f3
--- /dev/null
+++ b/pintos-progos/tests/userprog/create-bound.c
@@ -0,0 +1,14 @@
1/* Opens a file whose name spans the boundary between two pages.
2 This is valid, so it must succeed. */
3
4#include <syscall.h>
5#include "tests/userprog/boundary.h"
6#include "tests/lib.h"
7#include "tests/main.h"
8
9void
10test_main (void)
11{
12 msg ("create(\"quux.dat\"): %d",
13 create (copy_string_across_boundary ("quux.dat"), 0));
14}
diff --git a/pintos-progos/tests/userprog/create-bound.ck b/pintos-progos/tests/userprog/create-bound.ck
new file mode 100644
index 0000000..7656b7f
--- /dev/null
+++ b/pintos-progos/tests/userprog/create-bound.ck
@@ -0,0 +1,11 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(create-bound) begin
7(create-bound) create("quux.dat"): 1
8(create-bound) end
9create-bound: exit(0)
10EOF
11pass;
diff --git a/pintos-progos/tests/userprog/create-empty.c b/pintos-progos/tests/userprog/create-empty.c
new file mode 100644
index 0000000..fa26b43
--- /dev/null
+++ b/pintos-progos/tests/userprog/create-empty.c
@@ -0,0 +1,10 @@
1/* Tries to create a file with the empty string as its name. */
2
3#include "tests/lib.h"
4#include "tests/main.h"
5
6void
7test_main (void)
8{
9 msg ("create(\"\"): %d", create ("", 0));
10}
diff --git a/pintos-progos/tests/userprog/create-empty.ck b/pintos-progos/tests/userprog/create-empty.ck
new file mode 100644
index 0000000..93a1058
--- /dev/null
+++ b/pintos-progos/tests/userprog/create-empty.ck
@@ -0,0 +1,14 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF', <<'EOF']);
6(create-empty) begin
7(create-empty) create(""): 0
8(create-empty) end
9create-empty: exit(0)
10EOF
11(create-empty) begin
12create-empty: exit(-1)
13EOF
14pass;
diff --git a/pintos-progos/tests/userprog/create-exists.c b/pintos-progos/tests/userprog/create-exists.c
new file mode 100644
index 0000000..d395008
--- /dev/null
+++ b/pintos-progos/tests/userprog/create-exists.c
@@ -0,0 +1,16 @@
1/* Verifies that trying to create a file under a name that
2 already exists will fail. */
3
4#include <syscall.h>
5#include "tests/lib.h"
6#include "tests/main.h"
7
8void
9test_main (void)
10{
11 CHECK (create ("quux.dat", 0), "create quux.dat");
12 CHECK (create ("warble.dat", 0), "create warble.dat");
13 CHECK (!create ("quux.dat", 0), "try to re-create quux.dat");
14 CHECK (create ("baffle.dat", 0), "create baffle.dat");
15 CHECK (!create ("warble.dat", 0), "try to re-create quux.dat");
16}
diff --git a/pintos-progos/tests/userprog/create-exists.ck b/pintos-progos/tests/userprog/create-exists.ck
new file mode 100644
index 0000000..006885e
--- /dev/null
+++ b/pintos-progos/tests/userprog/create-exists.ck
@@ -0,0 +1,15 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(create-exists) begin
7(create-exists) create quux.dat
8(create-exists) create warble.dat
9(create-exists) try to re-create quux.dat
10(create-exists) create baffle.dat
11(create-exists) try to re-create quux.dat
12(create-exists) end
13create-exists: exit(0)
14EOF
15pass;
diff --git a/pintos-progos/tests/userprog/create-long.c b/pintos-progos/tests/userprog/create-long.c
new file mode 100644
index 0000000..16b31bd
--- /dev/null
+++ b/pintos-progos/tests/userprog/create-long.c
@@ -0,0 +1,17 @@
1/* Tries to create a file with a name that is much too long,
2 which must fail. */
3
4#include <string.h>
5#include <syscall.h>
6#include "tests/lib.h"
7#include "tests/main.h"
8
9void
10test_main (void)
11{
12 static char name[512];
13 memset (name, 'x', sizeof name);
14 name[sizeof name - 1] = '\0';
15
16 msg ("create(\"x...\"): %d", create (name, 0));
17}
diff --git a/pintos-progos/tests/userprog/create-long.ck b/pintos-progos/tests/userprog/create-long.ck
new file mode 100644
index 0000000..628411c
--- /dev/null
+++ b/pintos-progos/tests/userprog/create-long.ck
@@ -0,0 +1,11 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(create-long) begin
7(create-long) create("x..."): 0
8(create-long) end
9create-long: exit(0)
10EOF
11pass;
diff --git a/pintos-progos/tests/userprog/create-normal.c b/pintos-progos/tests/userprog/create-normal.c
new file mode 100644
index 0000000..3cbc463
--- /dev/null
+++ b/pintos-progos/tests/userprog/create-normal.c
@@ -0,0 +1,10 @@
1/* Creates an ordinary empty file. */
2
3#include "tests/lib.h"
4#include "tests/main.h"
5
6void
7test_main (void)
8{
9 CHECK (create ("quux.dat", 0), "create quux.dat");
10}
diff --git a/pintos-progos/tests/userprog/create-normal.ck b/pintos-progos/tests/userprog/create-normal.ck
new file mode 100644
index 0000000..ca74a6e
--- /dev/null
+++ b/pintos-progos/tests/userprog/create-normal.ck
@@ -0,0 +1,11 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(create-normal) begin
7(create-normal) create quux.dat
8(create-normal) end
9create-normal: exit(0)
10EOF
11pass;
diff --git a/pintos-progos/tests/userprog/create-null.c b/pintos-progos/tests/userprog/create-null.c
new file mode 100644
index 0000000..287cb23
--- /dev/null
+++ b/pintos-progos/tests/userprog/create-null.c
@@ -0,0 +1,11 @@
1/* Tries to create a file with the null pointer as its name.
2 The process must be terminated with exit code -1. */
3
4#include "tests/lib.h"
5#include "tests/main.h"
6
7void
8test_main (void)
9{
10 msg ("create(NULL): %d", create (NULL, 0));
11}
diff --git a/pintos-progos/tests/userprog/create-null.ck b/pintos-progos/tests/userprog/create-null.ck
new file mode 100644
index 0000000..09b7872
--- /dev/null
+++ b/pintos-progos/tests/userprog/create-null.ck
@@ -0,0 +1,9 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(create-null) begin
7create-null: exit(-1)
8EOF
9pass;
diff --git a/pintos-progos/tests/userprog/exec-arg.c b/pintos-progos/tests/userprog/exec-arg.c
new file mode 100644
index 0000000..82d0744
--- /dev/null
+++ b/pintos-progos/tests/userprog/exec-arg.c
@@ -0,0 +1,10 @@
1/* Tests argument passing to child processes. */
2
3#include <syscall.h>
4#include "tests/main.h"
5
6void
7test_main (void)
8{
9 wait (exec ("child-args childarg"));
10}
diff --git a/pintos-progos/tests/userprog/exec-arg.ck b/pintos-progos/tests/userprog/exec-arg.ck
new file mode 100644
index 0000000..b7533ed
--- /dev/null
+++ b/pintos-progos/tests/userprog/exec-arg.ck
@@ -0,0 +1,17 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(exec-arg) begin
7(args) begin
8(args) argc = 2
9(args) argv[0] = 'child-args'
10(args) argv[1] = 'childarg'
11(args) argv[2] = null
12(args) end
13child-args: exit(0)
14(exec-arg) end
15exec-arg: exit(0)
16EOF
17pass;
diff --git a/pintos-progos/tests/userprog/exec-bad-ptr.c b/pintos-progos/tests/userprog/exec-bad-ptr.c
new file mode 100644
index 0000000..0abadd3
--- /dev/null
+++ b/pintos-progos/tests/userprog/exec-bad-ptr.c
@@ -0,0 +1,11 @@
1/* Passes an invalid pointer to the exec system call.
2 The process must be terminated with -1 exit code. */
3
4#include <syscall.h>
5#include "tests/main.h"
6
7void
8test_main (void)
9{
10 exec ((char *) 0x20101234);
11}
diff --git a/pintos-progos/tests/userprog/exec-bad-ptr.ck b/pintos-progos/tests/userprog/exec-bad-ptr.ck
new file mode 100644
index 0000000..63f5f78
--- /dev/null
+++ b/pintos-progos/tests/userprog/exec-bad-ptr.ck
@@ -0,0 +1,13 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF', <<'EOF']);
6(exec-bad-ptr) begin
7(exec-bad-ptr) end
8exec-bad-ptr: exit(0)
9EOF
10(exec-bad-ptr) begin
11exec-bad-ptr: exit(-1)
12EOF
13pass;
diff --git a/pintos-progos/tests/userprog/exec-missing.c b/pintos-progos/tests/userprog/exec-missing.c
new file mode 100644
index 0000000..bf08cad
--- /dev/null
+++ b/pintos-progos/tests/userprog/exec-missing.c
@@ -0,0 +1,12 @@
1/* Tries to execute a nonexistent process.
2 The exec system call must return -1. */
3
4#include <syscall.h>
5#include "tests/lib.h"
6#include "tests/main.h"
7
8void
9test_main (void)
10{
11 msg ("exec(\"no-such-file\"): %d", exec ("no-such-file"));
12}
diff --git a/pintos-progos/tests/userprog/exec-missing.ck b/pintos-progos/tests/userprog/exec-missing.ck
new file mode 100644
index 0000000..0ef7aaa
--- /dev/null
+++ b/pintos-progos/tests/userprog/exec-missing.ck
@@ -0,0 +1,31 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF', <<'EOF', <<'EOF', <<'EOF']);
6(exec-missing) begin
7load: no-such-file: open failed
8(exec-missing) exec("no-such-file"): -1
9(exec-missing) end
10exec-missing: exit(0)
11EOF
12(exec-missing) begin
13(exec-missing) exec("no-such-file"): -1
14(exec-missing) end
15exec-missing: exit(0)
16EOF
17(exec-missing) begin
18load: no-such-file: open failed
19no-such-file: exit(-1)
20(exec-missing) exec("no-such-file"): -1
21(exec-missing) end
22exec-missing: exit(0)
23EOF
24(exec-missing) begin
25load: no-such-file: open failed
26(exec-missing) exec("no-such-file"): -1
27no-such-file: exit(-1)
28(exec-missing) end
29exec-missing: exit(0)
30EOF
31pass;
diff --git a/pintos-progos/tests/userprog/exec-multiple.c b/pintos-progos/tests/userprog/exec-multiple.c
new file mode 100644
index 0000000..ba4c26e
--- /dev/null
+++ b/pintos-progos/tests/userprog/exec-multiple.c
@@ -0,0 +1,14 @@
1/* Executes and waits for multiple child processes. */
2
3#include <syscall.h>
4#include "tests/lib.h"
5#include "tests/main.h"
6
7void
8test_main (void)
9{
10 wait (exec ("child-simple"));
11 wait (exec ("child-simple"));
12 wait (exec ("child-simple"));
13 wait (exec ("child-simple"));
14}
diff --git a/pintos-progos/tests/userprog/exec-multiple.ck b/pintos-progos/tests/userprog/exec-multiple.ck
new file mode 100644
index 0000000..99624cd
--- /dev/null
+++ b/pintos-progos/tests/userprog/exec-multiple.ck
@@ -0,0 +1,18 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(exec-multiple) begin
7(child-simple) run
8child-simple: exit(81)
9(child-simple) run
10child-simple: exit(81)
11(child-simple) run
12child-simple: exit(81)
13(child-simple) run
14child-simple: exit(81)
15(exec-multiple) end
16exec-multiple: exit(0)
17EOF
18pass;
diff --git a/pintos-progos/tests/userprog/exec-once.c b/pintos-progos/tests/userprog/exec-once.c
new file mode 100644
index 0000000..7bae5a1
--- /dev/null
+++ b/pintos-progos/tests/userprog/exec-once.c
@@ -0,0 +1,11 @@
1/* Executes and waits for a single child process. */
2
3#include <syscall.h>
4#include "tests/lib.h"
5#include "tests/main.h"
6
7void
8test_main (void)
9{
10 wait (exec ("child-simple"));
11}
diff --git a/pintos-progos/tests/userprog/exec-once.ck b/pintos-progos/tests/userprog/exec-once.ck
new file mode 100644
index 0000000..00b59ed
--- /dev/null
+++ b/pintos-progos/tests/userprog/exec-once.ck
@@ -0,0 +1,12 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(exec-once) begin
7(child-simple) run
8child-simple: exit(81)
9(exec-once) end
10exec-once: exit(0)
11EOF
12pass;
diff --git a/pintos-progos/tests/userprog/exit.c b/pintos-progos/tests/userprog/exit.c
new file mode 100644
index 0000000..cb4eb8f
--- /dev/null
+++ b/pintos-progos/tests/userprog/exit.c
@@ -0,0 +1,11 @@
1/* Tests the exit system call. */
2
3#include "tests/lib.h"
4#include "tests/main.h"
5
6void
7test_main (void)
8{
9 exit (57);
10 fail ("should have called exit(57)");
11}
diff --git a/pintos-progos/tests/userprog/exit.ck b/pintos-progos/tests/userprog/exit.ck
new file mode 100644
index 0000000..a552702
--- /dev/null
+++ b/pintos-progos/tests/userprog/exit.ck
@@ -0,0 +1,9 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(exit) begin
7exit: exit(57)
8EOF
9pass;
diff --git a/pintos-progos/tests/userprog/halt.c b/pintos-progos/tests/userprog/halt.c
new file mode 100644
index 0000000..4a99bce
--- /dev/null
+++ b/pintos-progos/tests/userprog/halt.c
@@ -0,0 +1,11 @@
1/* Tests the halt system call. */
2
3#include "tests/lib.h"
4#include "tests/main.h"
5
6void
7test_main (void)
8{
9 halt ();
10 fail ("should have halted");
11}
diff --git a/pintos-progos/tests/userprog/halt.ck b/pintos-progos/tests/userprog/halt.ck
new file mode 100644
index 0000000..1b701ed
--- /dev/null
+++ b/pintos-progos/tests/userprog/halt.ck
@@ -0,0 +1,15 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5
6our ($test);
7my (@output) = read_text_file ("$test.output");
8
9common_checks ("run", @output);
10
11fail "missing 'begin' message\n"
12 if !grep ($_ eq '(halt) begin', @output);
13fail "found 'fail' message--halt didn't really halt\n"
14 if grep ($_ eq '(halt) fail', @output);
15pass;
diff --git a/pintos-progos/tests/userprog/lib/.gitignore b/pintos-progos/tests/userprog/lib/.gitignore
new file mode 100644
index 0000000..a438335
--- /dev/null
+++ b/pintos-progos/tests/userprog/lib/.gitignore
@@ -0,0 +1 @@
*.d
diff --git a/pintos-progos/tests/userprog/lib/user/.dummy b/pintos-progos/tests/userprog/lib/user/.dummy
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/pintos-progos/tests/userprog/lib/user/.dummy
diff --git a/pintos-progos/tests/userprog/lib/user/.gitignore b/pintos-progos/tests/userprog/lib/user/.gitignore
new file mode 100644
index 0000000..a438335
--- /dev/null
+++ b/pintos-progos/tests/userprog/lib/user/.gitignore
@@ -0,0 +1 @@
*.d
diff --git a/pintos-progos/tests/userprog/multi-child-fd.c b/pintos-progos/tests/userprog/multi-child-fd.c
new file mode 100644
index 0000000..48de4b4
--- /dev/null
+++ b/pintos-progos/tests/userprog/multi-child-fd.c
@@ -0,0 +1,25 @@
1/* Opens a file and then runs a subprocess that tries to close
2 the file. (Pintos does not have inheritance of file handles,
3 so this must fail.) The parent process then attempts to use
4 the file handle, which must succeed. */
5
6#include <stdio.h>
7#include <syscall.h>
8#include "tests/userprog/sample.inc"
9#include "tests/lib.h"
10#include "tests/main.h"
11
12void
13test_main (void)
14{
15 char child_cmd[128];
16 int handle;
17
18 CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
19
20 snprintf (child_cmd, sizeof child_cmd, "child-close %d", handle);
21
22 msg ("wait(exec()) = %d", wait (exec (child_cmd)));
23
24 check_file_handle (handle, "sample.txt", sample, sizeof sample - 1);
25}
diff --git a/pintos-progos/tests/userprog/multi-child-fd.ck b/pintos-progos/tests/userprog/multi-child-fd.ck
new file mode 100644
index 0000000..d0b3a33
--- /dev/null
+++ b/pintos-progos/tests/userprog/multi-child-fd.ck
@@ -0,0 +1,25 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF', <<'EOF']);
6(multi-child-fd) begin
7(multi-child-fd) open "sample.txt"
8(child-close) begin
9(child-close) end
10child-close: exit(0)
11(multi-child-fd) wait(exec()) = 0
12(multi-child-fd) verified contents of "sample.txt"
13(multi-child-fd) end
14multi-child-fd: exit(0)
15EOF
16(multi-child-fd) begin
17(multi-child-fd) open "sample.txt"
18(child-close) begin
19child-close: exit(-1)
20(multi-child-fd) wait(exec()) = -1
21(multi-child-fd) verified contents of "sample.txt"
22(multi-child-fd) end
23multi-child-fd: exit(0)
24EOF
25pass;
diff --git a/pintos-progos/tests/userprog/multi-recurse.c b/pintos-progos/tests/userprog/multi-recurse.c
new file mode 100644
index 0000000..7172ec3
--- /dev/null
+++ b/pintos-progos/tests/userprog/multi-recurse.c
@@ -0,0 +1,34 @@
1/* Executes itself recursively to the depth indicated by the
2 first command-line argument. */
3
4#include <debug.h>
5#include <stdlib.h>
6#include <stdio.h>
7#include <syscall.h>
8#include "tests/lib.h"
9
10const char *test_name = "multi-recurse";
11
12int
13main (int argc UNUSED, char *argv[])
14{
15 int n = atoi (argv[1]);
16
17 msg ("begin %d", n);
18 if (n != 0)
19 {
20 char child_cmd[128];
21 pid_t child_pid;
22 int code;
23
24 snprintf (child_cmd, sizeof child_cmd, "multi-recurse %d", n - 1);
25 CHECK ((child_pid = exec (child_cmd)) != -1, "exec(\"%s\")", child_cmd);
26
27 code = wait (child_pid);
28 if (code != n - 1)
29 fail ("wait(exec(\"%s\")) returned %d", child_cmd, code);
30 }
31
32 msg ("end %d", n);
33 return n;
34}
diff --git a/pintos-progos/tests/userprog/multi-recurse.ck b/pintos-progos/tests/userprog/multi-recurse.ck
new file mode 100644
index 0000000..41eb4a6
--- /dev/null
+++ b/pintos-progos/tests/userprog/multi-recurse.ck
@@ -0,0 +1,70 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(multi-recurse) begin 15
7(multi-recurse) exec("multi-recurse 14")
8(multi-recurse) begin 14
9(multi-recurse) exec("multi-recurse 13")
10(multi-recurse) begin 13
11(multi-recurse) exec("multi-recurse 12")
12(multi-recurse) begin 12
13(multi-recurse) exec("multi-recurse 11")
14(multi-recurse) begin 11
15(multi-recurse) exec("multi-recurse 10")
16(multi-recurse) begin 10
17(multi-recurse) exec("multi-recurse 9")
18(multi-recurse) begin 9
19(multi-recurse) exec("multi-recurse 8")
20(multi-recurse) begin 8
21(multi-recurse) exec("multi-recurse 7")
22(multi-recurse) begin 7
23(multi-recurse) exec("multi-recurse 6")
24(multi-recurse) begin 6
25(multi-recurse) exec("multi-recurse 5")
26(multi-recurse) begin 5
27(multi-recurse) exec("multi-recurse 4")
28(multi-recurse) begin 4
29(multi-recurse) exec("multi-recurse 3")
30(multi-recurse) begin 3
31(multi-recurse) exec("multi-recurse 2")
32(multi-recurse) begin 2
33(multi-recurse) exec("multi-recurse 1")
34(multi-recurse) begin 1
35(multi-recurse) exec("multi-recurse 0")
36(multi-recurse) begin 0
37(multi-recurse) end 0
38multi-recurse: exit(0)
39(multi-recurse) end 1
40multi-recurse: exit(1)
41(multi-recurse) end 2
42multi-recurse: exit(2)
43(multi-recurse) end 3
44multi-recurse: exit(3)
45(multi-recurse) end 4
46multi-recurse: exit(4)
47(multi-recurse) end 5
48multi-recurse: exit(5)
49(multi-recurse) end 6
50multi-recurse: exit(6)
51(multi-recurse) end 7
52multi-recurse: exit(7)
53(multi-recurse) end 8
54multi-recurse: exit(8)
55(multi-recurse) end 9
56multi-recurse: exit(9)
57(multi-recurse) end 10
58multi-recurse: exit(10)
59(multi-recurse) end 11
60multi-recurse: exit(11)
61(multi-recurse) end 12
62multi-recurse: exit(12)
63(multi-recurse) end 13
64multi-recurse: exit(13)
65(multi-recurse) end 14
66multi-recurse: exit(14)
67(multi-recurse) end 15
68multi-recurse: exit(15)
69EOF
70pass;
diff --git a/pintos-progos/tests/userprog/no-vm/Make.tests b/pintos-progos/tests/userprog/no-vm/Make.tests
new file mode 100644
index 0000000..a545e18
--- /dev/null
+++ b/pintos-progos/tests/userprog/no-vm/Make.tests
@@ -0,0 +1,8 @@
1# -*- makefile -*-
2
3tests/userprog/no-vm_TESTS = tests/userprog/no-vm/multi-oom
4tests/userprog/no-vm_PROGS = $(tests/userprog/no-vm_TESTS)
5tests/userprog/no-vm/multi-oom_SRC = tests/userprog/no-vm/multi-oom.c \
6tests/lib.c
7
8tests/userprog/no-vm/multi-oom.output: TIMEOUT = 360
diff --git a/pintos-progos/tests/userprog/no-vm/Rubric b/pintos-progos/tests/userprog/no-vm/Rubric
new file mode 100644
index 0000000..c3816c6
--- /dev/null
+++ b/pintos-progos/tests/userprog/no-vm/Rubric
@@ -0,0 +1,3 @@
1Functionality of features that VM might break:
2
31 multi-oom
diff --git a/pintos-progos/tests/userprog/no-vm/multi-oom.c b/pintos-progos/tests/userprog/no-vm/multi-oom.c
new file mode 100644
index 0000000..6a4472d
--- /dev/null
+++ b/pintos-progos/tests/userprog/no-vm/multi-oom.c
@@ -0,0 +1,179 @@
1/* Recursively executes itself until the child fails to execute.
2 We expect that at least 30 copies can run.
3
4 We count how many children your kernel was able to execute
5 before it fails to start a new process. We require that,
6 if a process doesn't actually get to start, exec() must
7 return -1, not a valid PID.
8
9 We repeat this process 10 times, checking that your kernel
10 allows for the same level of depth every time.
11
12 In addition, some processes will spawn children that terminate
13 abnormally after allocating some resources.
14
15 Written by Godmar Back <godmar@gmail.com>
16 */
17
18#include <debug.h>
19#include <stdio.h>
20#include <string.h>
21#include <stdlib.h>
22#include <stdbool.h>
23#include <syscall.h>
24#include <random.h>
25#include "tests/lib.h"
26
27static const int EXPECTED_DEPTH_TO_PASS = 30;
28static const int EXPECTED_REPETITIONS = 10;
29
30const char *test_name = "multi-oom";
31
32enum child_termination_mode { RECURSE, CRASH };
33
34/* Spawn a recursive copy of ourselves, passing along instructions
35 for the child. */
36static pid_t
37spawn_child (int c, enum child_termination_mode mode)
38{
39 char child_cmd[128];
40 snprintf (child_cmd, sizeof child_cmd,
41 "%s %d %s", test_name, c, mode == CRASH ? "-k" : "");
42 return exec (child_cmd);
43}
44
45/* Open a number of files (and fail to close them).
46 The kernel must free any kernel resources associated
47 with these file descriptors. */
48static void
49consume_some_resources (void)
50{
51 int fd, fdmax = 126;
52
53 /* Open as many files as we can, up to fdmax.
54 Depending on how file descriptors are allocated inside
55 the kernel, open() may fail if the kernel is low on memory.
56 A low-memory condition in open() should not lead to the
57 termination of the process. */
58 for (fd = 0; fd < fdmax; fd++)
59 if (open (test_name) == -1)
60 break;
61}
62
63/* Consume some resources, then terminate this process
64 in some abnormal way. */
65static int NO_INLINE
66consume_some_resources_and_die (int seed)
67{
68 consume_some_resources ();
69 random_init (seed);
70 int *PHYS_BASE = (int *)0xC0000000;
71
72 switch (random_ulong () % 5)
73 {
74 case 0:
75 *(int *) NULL = 42;
76
77 case 1:
78 return *(int *) NULL;
79
80 case 2:
81 return *PHYS_BASE;
82
83 case 3:
84 *PHYS_BASE = 42;
85
86 case 4:
87 open ((char *)PHYS_BASE);
88 exit (-1);
89
90 default:
91 NOT_REACHED ();
92 }
93 return 0;
94}
95
96/* The first copy is invoked without command line arguments.
97 Subsequent copies are invoked with a parameter 'depth'
98 that describes how many parent processes preceded them.
99 Each process spawns one or multiple recursive copies of
100 itself, passing 'depth+1' as depth.
101
102 Some children are started with the '-k' flag, which will
103 result in abnormal termination.
104 */
105int
106main (int argc, char *argv[])
107{
108 int n;
109
110 n = argc > 1 ? atoi (argv[1]) : 0;
111 bool is_at_root = (n == 0);
112 if (is_at_root)
113 msg ("begin");
114
115 /* If -k is passed, crash this process. */
116 if (argc > 2 && !strcmp(argv[2], "-k"))
117 {
118 consume_some_resources_and_die (n);
119 NOT_REACHED ();
120 }
121
122 int howmany = is_at_root ? EXPECTED_REPETITIONS : 1;
123 int i, expected_depth = -1;
124
125 for (i = 0; i < howmany; i++)
126 {
127 pid_t child_pid;
128
129 /* Spawn a child that will be abnormally terminated.
130 To speed the test up, do this only for processes
131 spawned at a certain depth. */
132 if (n > EXPECTED_DEPTH_TO_PASS/2)
133 {
134 child_pid = spawn_child (n + 1, CRASH);
135 if (child_pid != -1)
136 {
137 if (wait (child_pid) != -1)
138 fail ("crashed child should return -1.");
139 }
140 /* If spawning this child failed, so should
141 the next spawn_child below. */
142 }
143
144 /* Now spawn the child that will recurse. */
145 child_pid = spawn_child (n + 1, RECURSE);
146
147 /* If maximum depth is reached, return result. */
148 if (child_pid == -1)
149 return n;
150
151 /* Else wait for child to report how deeply it was able to recurse. */
152 int reached_depth = wait (child_pid);
153 if (reached_depth == -1)
154 fail ("wait returned -1.");
155
156 /* Record the depth reached during the first run; on subsequent
157 runs, fail if those runs do not match the depth achieved on the
158 first run. */
159 if (i == 0)
160 expected_depth = reached_depth;
161 else if (expected_depth != reached_depth)
162 fail ("after run %d/%d, expected depth %d, actual depth %d.",
163 i, howmany, expected_depth, reached_depth);
164 ASSERT (expected_depth == reached_depth);
165 }
166
167 consume_some_resources ();
168
169 if (n == 0)
170 {
171 if (expected_depth < EXPECTED_DEPTH_TO_PASS)
172 fail ("should have forked at least %d times.", EXPECTED_DEPTH_TO_PASS);
173 msg ("success. program forked %d times.", howmany);
174 msg ("end");
175 }
176
177 return expected_depth;
178}
179// vim: sw=2
diff --git a/pintos-progos/tests/userprog/no-vm/multi-oom.ck b/pintos-progos/tests/userprog/no-vm/multi-oom.ck
new file mode 100644
index 0000000..59a0bcd
--- /dev/null
+++ b/pintos-progos/tests/userprog/no-vm/multi-oom.ck
@@ -0,0 +1,10 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_USER_FAULTS => 1, IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(multi-oom) begin
7(multi-oom) success. program forked 10 times.
8(multi-oom) end
9EOF
10pass;
diff --git a/pintos-progos/tests/userprog/null.ck b/pintos-progos/tests/userprog/null.ck
new file mode 100644
index 0000000..980de35
--- /dev/null
+++ b/pintos-progos/tests/userprog/null.ck
@@ -0,0 +1,8 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6system call!
7EOF
8pass;
diff --git a/pintos-progos/tests/userprog/open-bad-ptr.c b/pintos-progos/tests/userprog/open-bad-ptr.c
new file mode 100644
index 0000000..9cd4edf
--- /dev/null
+++ b/pintos-progos/tests/userprog/open-bad-ptr.c
@@ -0,0 +1,13 @@
1/* Passes an invalid pointer to the open system call.
2 The process must be terminated with -1 exit code. */
3
4#include <syscall.h>
5#include "tests/lib.h"
6#include "tests/main.h"
7
8void
9test_main (void)
10{
11 msg ("open(0x20101234): %d", open ((char *) 0x20101234));
12 fail ("should have called exit(-1)");
13}
diff --git a/pintos-progos/tests/userprog/open-bad-ptr.ck b/pintos-progos/tests/userprog/open-bad-ptr.ck
new file mode 100644
index 0000000..45349e2
--- /dev/null
+++ b/pintos-progos/tests/userprog/open-bad-ptr.ck
@@ -0,0 +1,13 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF', <<'EOF']);
6(open-bad-ptr) begin
7(open-bad-ptr) end
8open-bad-ptr: exit(0)
9EOF
10(open-bad-ptr) begin
11open-bad-ptr: exit(-1)
12EOF
13pass;
diff --git a/pintos-progos/tests/userprog/open-boundary.c b/pintos-progos/tests/userprog/open-boundary.c
new file mode 100644
index 0000000..cc8ff8b
--- /dev/null
+++ b/pintos-progos/tests/userprog/open-boundary.c
@@ -0,0 +1,14 @@
1/* Creates a file whose name spans the boundary between two pages.
2 This is valid, so it must succeed. */
3
4#include <syscall.h>
5#include "tests/userprog/boundary.h"
6#include "tests/lib.h"
7#include "tests/main.h"
8
9void
10test_main (void)
11{
12 CHECK (open (copy_string_across_boundary ("sample.txt")) > 1,
13 "open \"sample.txt\"");
14}
diff --git a/pintos-progos/tests/userprog/open-boundary.ck b/pintos-progos/tests/userprog/open-boundary.ck
new file mode 100644
index 0000000..8060d22
--- /dev/null
+++ b/pintos-progos/tests/userprog/open-boundary.ck
@@ -0,0 +1,11 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(open-boundary) begin
7(open-boundary) open "sample.txt"
8(open-boundary) end
9open-boundary: exit(0)
10EOF
11pass;
diff --git a/pintos-progos/tests/userprog/open-empty.c b/pintos-progos/tests/userprog/open-empty.c
new file mode 100644
index 0000000..3ea9907
--- /dev/null
+++ b/pintos-progos/tests/userprog/open-empty.c
@@ -0,0 +1,13 @@
1/* Tries to open a file with the empty string as its name. */
2
3#include <syscall.h>
4#include "tests/lib.h"
5#include "tests/main.h"
6
7void
8test_main (void)
9{
10 int handle = open ("");
11 if (handle != -1)
12 fail ("open() returned %d instead of -1", handle);
13}
diff --git a/pintos-progos/tests/userprog/open-empty.ck b/pintos-progos/tests/userprog/open-empty.ck
new file mode 100644
index 0000000..885fb41
--- /dev/null
+++ b/pintos-progos/tests/userprog/open-empty.ck
@@ -0,0 +1,10 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(open-empty) begin
7(open-empty) end
8open-empty: exit(0)
9EOF
10pass;
diff --git a/pintos-progos/tests/userprog/open-missing.c b/pintos-progos/tests/userprog/open-missing.c
new file mode 100644
index 0000000..13ecbda
--- /dev/null
+++ b/pintos-progos/tests/userprog/open-missing.c
@@ -0,0 +1,13 @@
1/* Tries to open a nonexistent file. */
2
3#include <syscall.h>
4#include "tests/lib.h"
5#include "tests/main.h"
6
7void
8test_main (void)
9{
10 int handle = open ("no-such-file");
11 if (handle != -1)
12 fail ("open() returned %d", handle);
13}
diff --git a/pintos-progos/tests/userprog/open-missing.ck b/pintos-progos/tests/userprog/open-missing.ck
new file mode 100644
index 0000000..d72d878
--- /dev/null
+++ b/pintos-progos/tests/userprog/open-missing.ck
@@ -0,0 +1,10 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(open-missing) begin
7(open-missing) end
8open-missing: exit(0)
9EOF
10pass;
diff --git a/pintos-progos/tests/userprog/open-normal.c b/pintos-progos/tests/userprog/open-normal.c
new file mode 100644
index 0000000..5132465
--- /dev/null
+++ b/pintos-progos/tests/userprog/open-normal.c
@@ -0,0 +1,13 @@
1/* Open a file. */
2
3#include <syscall.h>
4#include "tests/lib.h"
5#include "tests/main.h"
6
7void
8test_main (void)
9{
10 int handle = open ("sample.txt");
11 if (handle < 2)
12 fail ("open() returned %d", handle);
13}
diff --git a/pintos-progos/tests/userprog/open-normal.ck b/pintos-progos/tests/userprog/open-normal.ck
new file mode 100644
index 0000000..4f6c342
--- /dev/null
+++ b/pintos-progos/tests/userprog/open-normal.ck
@@ -0,0 +1,10 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(open-normal) begin
7(open-normal) end
8open-normal: exit(0)
9EOF
10pass;
diff --git a/pintos-progos/tests/userprog/open-null.c b/pintos-progos/tests/userprog/open-null.c
new file mode 100644
index 0000000..bb418b8
--- /dev/null
+++ b/pintos-progos/tests/userprog/open-null.c
@@ -0,0 +1,12 @@
1/* Tries to open a file with the null pointer as its name.
2 The process must be terminated with exit code -1. */
3
4#include <stddef.h>
5#include <syscall.h>
6#include "tests/main.h"
7
8void
9test_main (void)
10{
11 open (NULL);
12}
diff --git a/pintos-progos/tests/userprog/open-null.ck b/pintos-progos/tests/userprog/open-null.ck
new file mode 100644
index 0000000..b4a3bcb
--- /dev/null
+++ b/pintos-progos/tests/userprog/open-null.ck
@@ -0,0 +1,13 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF', <<'EOF']);
6(open-null) begin
7(open-null) end
8open-null: exit(0)
9EOF
10(open-null) begin
11open-null: exit(-1)
12EOF
13pass;
diff --git a/pintos-progos/tests/userprog/open-twice.c b/pintos-progos/tests/userprog/open-twice.c
new file mode 100644
index 0000000..dd333af
--- /dev/null
+++ b/pintos-progos/tests/userprog/open-twice.c
@@ -0,0 +1,19 @@
1/* Tries to open the same file twice,
2 which must succeed and must return a different file descriptor
3 in each case. */
4
5#include <syscall.h>
6#include "tests/lib.h"
7#include "tests/main.h"
8
9void
10test_main (void)
11{
12 int h1 = open ("sample.txt");
13 int h2 = open ("sample.txt");
14
15 CHECK ((h1 = open ("sample.txt")) > 1, "open \"sample.txt\" once");
16 CHECK ((h2 = open ("sample.txt")) > 1, "open \"sample.txt\" again");
17 if (h1 == h2)
18 fail ("open() returned %d both times", h1);
19}
diff --git a/pintos-progos/tests/userprog/open-twice.ck b/pintos-progos/tests/userprog/open-twice.ck
new file mode 100644
index 0000000..64fa805
--- /dev/null
+++ b/pintos-progos/tests/userprog/open-twice.ck
@@ -0,0 +1,12 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(open-twice) begin
7(open-twice) open "sample.txt" once
8(open-twice) open "sample.txt" again
9(open-twice) end
10open-twice: exit(0)
11EOF
12pass;
diff --git a/pintos-progos/tests/userprog/read-bad-fd.c b/pintos-progos/tests/userprog/read-bad-fd.c
new file mode 100644
index 0000000..a8b190d
--- /dev/null
+++ b/pintos-progos/tests/userprog/read-bad-fd.c
@@ -0,0 +1,21 @@
1/* Tries to read from an invalid fd,
2 which must either fail silently or terminate the process with
3 exit code -1. */
4
5#include <limits.h>
6#include <syscall.h>
7#include "tests/lib.h"
8#include "tests/main.h"
9
10void
11test_main (void)
12{
13 char buf;
14 read (0x20101234, &buf, 1);
15 read (5, &buf, 1);
16 read (1234, &buf, 1);
17 read (-1, &buf, 1);
18 read (-1024, &buf, 1);
19 read (INT_MIN, &buf, 1);
20 read (INT_MAX, &buf, 1);
21}
diff --git a/pintos-progos/tests/userprog/read-bad-fd.ck b/pintos-progos/tests/userprog/read-bad-fd.ck
new file mode 100644
index 0000000..5fedcc7
--- /dev/null
+++ b/pintos-progos/tests/userprog/read-bad-fd.ck
@@ -0,0 +1,13 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF', <<'EOF']);
6(read-bad-fd) begin
7(read-bad-fd) end
8read-bad-fd: exit(0)
9EOF
10(read-bad-fd) begin
11read-bad-fd: exit(-1)
12EOF
13pass;
diff --git a/pintos-progos/tests/userprog/read-bad-ptr.c b/pintos-progos/tests/userprog/read-bad-ptr.c
new file mode 100644
index 0000000..8fe756e
--- /dev/null
+++ b/pintos-progos/tests/userprog/read-bad-ptr.c
@@ -0,0 +1,16 @@
1/* Passes an invalid pointer to the read system call.
2 The process must be terminated with -1 exit code. */
3
4#include <syscall.h>
5#include "tests/lib.h"
6#include "tests/main.h"
7
8void
9test_main (void)
10{
11 int handle;
12 CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
13
14 read (handle, (char *) 0xc0100000, 123);
15 fail ("should not have survived read()");
16}
diff --git a/pintos-progos/tests/userprog/read-bad-ptr.ck b/pintos-progos/tests/userprog/read-bad-ptr.ck
new file mode 100644
index 0000000..d10accf
--- /dev/null
+++ b/pintos-progos/tests/userprog/read-bad-ptr.ck
@@ -0,0 +1,15 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF', <<'EOF']);
6(read-bad-ptr) begin
7(read-bad-ptr) open "sample.txt"
8(read-bad-ptr) end
9read-bad-ptr: exit(0)
10EOF
11(read-bad-ptr) begin
12(read-bad-ptr) open "sample.txt"
13read-bad-ptr: exit(-1)
14EOF
15pass;
diff --git a/pintos-progos/tests/userprog/read-boundary.c b/pintos-progos/tests/userprog/read-boundary.c
new file mode 100644
index 0000000..9c19966
--- /dev/null
+++ b/pintos-progos/tests/userprog/read-boundary.c
@@ -0,0 +1,30 @@
1/* Reads data spanning two pages in virtual address space,
2 which must succeed. */
3
4#include <string.h>
5#include <syscall.h>
6#include "tests/userprog/boundary.h"
7#include "tests/userprog/sample.inc"
8#include "tests/lib.h"
9#include "tests/main.h"
10
11void
12test_main (void)
13{
14 int handle;
15 int byte_cnt;
16 char *buffer;
17
18 CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
19
20 buffer = get_boundary_area () - sizeof sample / 2;
21 byte_cnt = read (handle, buffer, sizeof sample - 1);
22 if (byte_cnt != sizeof sample - 1)
23 fail ("read() returned %d instead of %zu", byte_cnt, sizeof sample - 1);
24 else if (strcmp (sample, buffer))
25 {
26 msg ("expected text:\n%s", sample);
27 msg ("text actually read:\n%s", buffer);
28 fail ("expected text differs from actual");
29 }
30}
diff --git a/pintos-progos/tests/userprog/read-boundary.ck b/pintos-progos/tests/userprog/read-boundary.ck
new file mode 100644
index 0000000..08dc161
--- /dev/null
+++ b/pintos-progos/tests/userprog/read-boundary.ck
@@ -0,0 +1,11 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(read-boundary) begin
7(read-boundary) open "sample.txt"
8(read-boundary) end
9read-boundary: exit(0)
10EOF
11pass;
diff --git a/pintos-progos/tests/userprog/read-normal.c b/pintos-progos/tests/userprog/read-normal.c
new file mode 100644
index 0000000..16d15cc
--- /dev/null
+++ b/pintos-progos/tests/userprog/read-normal.c
@@ -0,0 +1,11 @@
1/* Try reading a file in the most normal way. */
2
3#include "tests/userprog/sample.inc"
4#include "tests/lib.h"
5#include "tests/main.h"
6
7void
8test_main (void)
9{
10 check_file ("sample.txt", sample, sizeof sample - 1);
11}
diff --git a/pintos-progos/tests/userprog/read-normal.ck b/pintos-progos/tests/userprog/read-normal.ck
new file mode 100644
index 0000000..0ed2998
--- /dev/null
+++ b/pintos-progos/tests/userprog/read-normal.ck
@@ -0,0 +1,13 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(read-normal) begin
7(read-normal) open "sample.txt" for verification
8(read-normal) verified contents of "sample.txt"
9(read-normal) close "sample.txt"
10(read-normal) end
11read-normal: exit(0)
12EOF
13pass;
diff --git a/pintos-progos/tests/userprog/read-stdout.c b/pintos-progos/tests/userprog/read-stdout.c
new file mode 100644
index 0000000..d0630b9
--- /dev/null
+++ b/pintos-progos/tests/userprog/read-stdout.c
@@ -0,0 +1,14 @@
1/* Try reading from fd 1 (stdout),
2 which may just fail or terminate the process with -1 exit
3 code. */
4
5#include <stdio.h>
6#include <syscall.h>
7#include "tests/main.h"
8
9void
10test_main (void)
11{
12 char buf;
13 read (STDOUT_FILENO, &buf, 1);
14}
diff --git a/pintos-progos/tests/userprog/read-stdout.ck b/pintos-progos/tests/userprog/read-stdout.ck
new file mode 100644
index 0000000..7d87b52
--- /dev/null
+++ b/pintos-progos/tests/userprog/read-stdout.ck
@@ -0,0 +1,13 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF', <<'EOF']);
6(read-stdout) begin
7(read-stdout) end
8read-stdout: exit(0)
9EOF
10(read-stdout) begin
11read-stdout: exit(-1)
12EOF
13pass;
diff --git a/pintos-progos/tests/userprog/read-zero.c b/pintos-progos/tests/userprog/read-zero.c
new file mode 100644
index 0000000..e441817
--- /dev/null
+++ b/pintos-progos/tests/userprog/read-zero.c
@@ -0,0 +1,22 @@
1/* Try a 0-byte read, which should return 0 without reading
2 anything. */
3
4#include <syscall.h>
5#include "tests/lib.h"
6#include "tests/main.h"
7
8void
9test_main (void)
10{
11 int handle, byte_cnt;
12 char buf;
13
14 CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
15
16 buf = 123;
17 byte_cnt = read (handle, &buf, 0);
18 if (byte_cnt != 0)
19 fail ("read() returned %d instead of 0", byte_cnt);
20 else if (buf != 123)
21 fail ("0-byte read() modified buffer");
22}
diff --git a/pintos-progos/tests/userprog/read-zero.ck b/pintos-progos/tests/userprog/read-zero.ck
new file mode 100644
index 0000000..8346dbc
--- /dev/null
+++ b/pintos-progos/tests/userprog/read-zero.ck
@@ -0,0 +1,11 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(read-zero) begin
7(read-zero) open "sample.txt"
8(read-zero) end
9read-zero: exit(0)
10EOF
11pass;
diff --git a/pintos-progos/tests/userprog/rox-child.c b/pintos-progos/tests/userprog/rox-child.c
new file mode 100644
index 0000000..30afba2
--- /dev/null
+++ b/pintos-progos/tests/userprog/rox-child.c
@@ -0,0 +1,5 @@
1/* Ensure that the executable of a running process cannot be
2 modified, even by a child process. */
3
4#define CHILD_CNT "1"
5#include "tests/userprog/rox-child.inc"
diff --git a/pintos-progos/tests/userprog/rox-child.ck b/pintos-progos/tests/userprog/rox-child.ck
new file mode 100644
index 0000000..e6363fb
--- /dev/null
+++ b/pintos-progos/tests/userprog/rox-child.ck
@@ -0,0 +1,20 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(rox-child) begin
7(rox-child) open "child-rox"
8(rox-child) read "child-rox"
9(rox-child) write "child-rox"
10(rox-child) exec "child-rox 1"
11(child-rox) begin
12(child-rox) try to write "child-rox"
13(child-rox) try to write "child-rox"
14(child-rox) end
15child-rox: exit(12)
16(rox-child) write "child-rox"
17(rox-child) end
18rox-child: exit(0)
19EOF
20pass;
diff --git a/pintos-progos/tests/userprog/rox-child.inc b/pintos-progos/tests/userprog/rox-child.inc
new file mode 100644
index 0000000..1e2ade9
--- /dev/null
+++ b/pintos-progos/tests/userprog/rox-child.inc
@@ -0,0 +1,33 @@
1/* -*- c -*- */
2
3#include <syscall.h>
4#include "tests/lib.h"
5#include "tests/main.h"
6
7void
8test_main (void)
9{
10 const char *child_cmd = "child-rox " CHILD_CNT;
11 int handle;
12 pid_t child;
13 char buffer[16];
14
15 /* Open child-rox, read from it, write back same data. */
16 CHECK ((handle = open ("child-rox")) > 1, "open \"child-rox\"");
17 CHECK (read (handle, buffer, sizeof buffer) == (int) sizeof buffer,
18 "read \"child-rox\"");
19 seek (handle, 0);
20 CHECK (write (handle, buffer, sizeof buffer) == (int) sizeof buffer,
21 "write \"child-rox\"");
22
23 /* Execute child-rox and wait for it. */
24 CHECK ((child = exec (child_cmd)) != -1, "exec \"%s\"", child_cmd);
25 quiet = true;
26 CHECK (wait (child) == 12, "wait for child");
27 quiet = false;
28
29 /* Write to child-rox again. */
30 seek (handle, 0);
31 CHECK (write (handle, buffer, sizeof buffer) == (int) sizeof buffer,
32 "write \"child-rox\"");
33}
diff --git a/pintos-progos/tests/userprog/rox-multichild.c b/pintos-progos/tests/userprog/rox-multichild.c
new file mode 100644
index 0000000..8e74dab
--- /dev/null
+++ b/pintos-progos/tests/userprog/rox-multichild.c
@@ -0,0 +1,5 @@
1/* Ensure that the executable of a running process cannot be
2 modified, even in the presence of multiple children. */
3
4#define CHILD_CNT "5"
5#include "tests/userprog/rox-child.inc"
diff --git a/pintos-progos/tests/userprog/rox-multichild.ck b/pintos-progos/tests/userprog/rox-multichild.ck
new file mode 100644
index 0000000..14b27db
--- /dev/null
+++ b/pintos-progos/tests/userprog/rox-multichild.ck
@@ -0,0 +1,44 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(rox-multichild) begin
7(rox-multichild) open "child-rox"
8(rox-multichild) read "child-rox"
9(rox-multichild) write "child-rox"
10(rox-multichild) exec "child-rox 5"
11(child-rox) begin
12(child-rox) try to write "child-rox"
13(child-rox) exec "child-rox 4"
14(child-rox) begin
15(child-rox) try to write "child-rox"
16(child-rox) exec "child-rox 3"
17(child-rox) begin
18(child-rox) try to write "child-rox"
19(child-rox) exec "child-rox 2"
20(child-rox) begin
21(child-rox) try to write "child-rox"
22(child-rox) exec "child-rox 1"
23(child-rox) begin
24(child-rox) try to write "child-rox"
25(child-rox) try to write "child-rox"
26(child-rox) end
27child-rox: exit(12)
28(child-rox) try to write "child-rox"
29(child-rox) end
30child-rox: exit(12)
31(child-rox) try to write "child-rox"
32(child-rox) end
33child-rox: exit(12)
34(child-rox) try to write "child-rox"
35(child-rox) end
36child-rox: exit(12)
37(child-rox) try to write "child-rox"
38(child-rox) end
39child-rox: exit(12)
40(rox-multichild) write "child-rox"
41(rox-multichild) end
42rox-multichild: exit(0)
43EOF
44pass;
diff --git a/pintos-progos/tests/userprog/rox-simple.c b/pintos-progos/tests/userprog/rox-simple.c
new file mode 100644
index 0000000..e84a064
--- /dev/null
+++ b/pintos-progos/tests/userprog/rox-simple.c
@@ -0,0 +1,19 @@
1/* Ensure that the executable of a running process cannot be
2 modified. */
3
4#include <syscall.h>
5#include "tests/lib.h"
6#include "tests/main.h"
7
8void
9test_main (void)
10{
11 int handle;
12 char buffer[16];
13
14 CHECK ((handle = open ("rox-simple")) > 1, "open \"rox-simple\"");
15 CHECK (read (handle, buffer, sizeof buffer) == (int) sizeof buffer,
16 "read \"rox-simple\"");
17 CHECK (write (handle, buffer, sizeof buffer) == 0,
18 "try to write \"rox-simple\"");
19}
diff --git a/pintos-progos/tests/userprog/rox-simple.ck b/pintos-progos/tests/userprog/rox-simple.ck
new file mode 100644
index 0000000..c9dcc66
--- /dev/null
+++ b/pintos-progos/tests/userprog/rox-simple.ck
@@ -0,0 +1,13 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(rox-simple) begin
7(rox-simple) open "rox-simple"
8(rox-simple) read "rox-simple"
9(rox-simple) try to write "rox-simple"
10(rox-simple) end
11rox-simple: exit(0)
12EOF
13pass;
diff --git a/pintos-progos/tests/userprog/sample.inc b/pintos-progos/tests/userprog/sample.inc
new file mode 100644
index 0000000..59f2bcb
--- /dev/null
+++ b/pintos-progos/tests/userprog/sample.inc
@@ -0,0 +1,6 @@
1char sample[] = {
2 "\"Amazing Electronic Fact: If you scuffed your feet long enough without\n"
3 " touching anything, you would build up so many electrons that your\n"
4 " finger would explode! But this is nothing to worry about unless you\n"
5 " have carpeting.\" --Dave Barry\n"
6};
diff --git a/pintos-progos/tests/userprog/sample.txt b/pintos-progos/tests/userprog/sample.txt
new file mode 100644
index 0000000..5050fec
--- /dev/null
+++ b/pintos-progos/tests/userprog/sample.txt
@@ -0,0 +1,4 @@
1"Amazing Electronic Fact: If you scuffed your feet long enough without
2 touching anything, you would build up so many electrons that your
3 finger would explode! But this is nothing to worry about unless you
4 have carpeting." --Dave Barry
diff --git a/pintos-progos/tests/userprog/sc-bad-arg.c b/pintos-progos/tests/userprog/sc-bad-arg.c
new file mode 100644
index 0000000..0b512a0
--- /dev/null
+++ b/pintos-progos/tests/userprog/sc-bad-arg.c
@@ -0,0 +1,17 @@
1/* Sticks a system call number (SYS_EXIT) at the very top of the
2 stack, then invokes a system call with the stack pointer
3 (%esp) set to its address. The process must be terminated
4 with -1 exit code because the argument to the system call
5 would be above the top of the user address space. */
6
7#include <syscall-nr.h>
8#include "tests/lib.h"
9#include "tests/main.h"
10
11void
12test_main (void)
13{
14 asm volatile ("movl $0xbffffffc, %%esp; movl %0, (%%esp); int $0x30"
15 : : "i" (SYS_EXIT));
16 fail ("should have called exit(-1)");
17}
diff --git a/pintos-progos/tests/userprog/sc-bad-arg.ck b/pintos-progos/tests/userprog/sc-bad-arg.ck
new file mode 100644
index 0000000..8981105
--- /dev/null
+++ b/pintos-progos/tests/userprog/sc-bad-arg.ck
@@ -0,0 +1,9 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(sc-bad-arg) begin
7sc-bad-arg: exit(-1)
8EOF
9pass;
diff --git a/pintos-progos/tests/userprog/sc-bad-sp.c b/pintos-progos/tests/userprog/sc-bad-sp.c
new file mode 100644
index 0000000..39cce84
--- /dev/null
+++ b/pintos-progos/tests/userprog/sc-bad-sp.c
@@ -0,0 +1,20 @@
1/* Invokes a system call with the stack pointer (%esp) set to a
2 bad address. The process must be terminated with -1 exit
3 code.
4
5 For Project 3: The bad address lies approximately 64MB below
6 the code segment, so there is no ambiguity that this attempt
7 must be rejected even after stack growth is implemented.
8 Moreover, a good stack growth heuristics should probably not
9 grow the stack for the purpose of reading the system call
10 number and arguments. */
11
12#include "tests/lib.h"
13#include "tests/main.h"
14
15void
16test_main (void)
17{
18 asm volatile ("movl $.-(64*1024*1024), %esp; int $0x30");
19 fail ("should have called exit(-1)");
20}
diff --git a/pintos-progos/tests/userprog/sc-bad-sp.ck b/pintos-progos/tests/userprog/sc-bad-sp.ck
new file mode 100644
index 0000000..498cec1
--- /dev/null
+++ b/pintos-progos/tests/userprog/sc-bad-sp.ck
@@ -0,0 +1,9 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(sc-bad-sp) begin
7sc-bad-sp: exit(-1)
8EOF
9pass;
diff --git a/pintos-progos/tests/userprog/sc-boundary-2.c b/pintos-progos/tests/userprog/sc-boundary-2.c
new file mode 100644
index 0000000..8acf036
--- /dev/null
+++ b/pintos-progos/tests/userprog/sc-boundary-2.c
@@ -0,0 +1,22 @@
1/* Invokes a system call with one byte of the system call's
2 argument on a separate page from the rest of the bytes. This
3 must work. */
4
5#include <syscall-nr.h>
6#include "tests/userprog/boundary.h"
7#include "tests/lib.h"
8#include "tests/main.h"
9
10void
11test_main (void)
12{
13 /* Make one byte of a syscall argument hang over into a second
14 page. */
15 int *p = (int *) ((char *) get_boundary_area () - 7);
16 p[0] = SYS_EXIT;
17 p[1] = 67;
18
19 /* Invoke the system call. */
20 asm volatile ("movl %0, %%esp; int $0x30" : : "g" (p));
21 fail ("should have called exit(67)");
22}
diff --git a/pintos-progos/tests/userprog/sc-boundary-2.ck b/pintos-progos/tests/userprog/sc-boundary-2.ck
new file mode 100644
index 0000000..43766bf
--- /dev/null
+++ b/pintos-progos/tests/userprog/sc-boundary-2.ck
@@ -0,0 +1,9 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(sc-boundary-2) begin
7sc-boundary-2: exit(67)
8EOF
9pass;
diff --git a/pintos-progos/tests/userprog/sc-boundary.c b/pintos-progos/tests/userprog/sc-boundary.c
new file mode 100644
index 0000000..d889535
--- /dev/null
+++ b/pintos-progos/tests/userprog/sc-boundary.c
@@ -0,0 +1,22 @@
1/* Invokes a system call with the system call number and its
2 argument on separate pages. This must work. */
3
4#include <syscall-nr.h>
5#include "tests/userprog/boundary.h"
6#include "tests/lib.h"
7#include "tests/main.h"
8
9void
10test_main (void)
11{
12 /* Put a syscall number at the end of one page
13 and its argument at the beginning of another. */
14 int *p = get_boundary_area ();
15 p--;
16 p[0] = SYS_EXIT;
17 p[1] = 42;
18
19 /* Invoke the system call. */
20 asm volatile ("movl %0, %%esp; int $0x30" : : "g" (p));
21 fail ("should have called exit(42)");
22}
diff --git a/pintos-progos/tests/userprog/sc-boundary.ck b/pintos-progos/tests/userprog/sc-boundary.ck
new file mode 100644
index 0000000..3f7cbaf
--- /dev/null
+++ b/pintos-progos/tests/userprog/sc-boundary.ck
@@ -0,0 +1,9 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(sc-boundary) begin
7sc-boundary: exit(42)
8EOF
9pass;
diff --git a/pintos-progos/tests/userprog/wait-bad-pid.c b/pintos-progos/tests/userprog/wait-bad-pid.c
new file mode 100644
index 0000000..3fe8ee4
--- /dev/null
+++ b/pintos-progos/tests/userprog/wait-bad-pid.c
@@ -0,0 +1,11 @@
1/* Waits for an invalid pid. This may fail or terminate the
2 process with -1 exit code. */
3
4#include <syscall.h>
5#include "tests/main.h"
6
7void
8test_main (void)
9{
10 wait ((pid_t) 0x0c020301);
11}
diff --git a/pintos-progos/tests/userprog/wait-bad-pid.ck b/pintos-progos/tests/userprog/wait-bad-pid.ck
new file mode 100644
index 0000000..db63fb9
--- /dev/null
+++ b/pintos-progos/tests/userprog/wait-bad-pid.ck
@@ -0,0 +1,13 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF', <<'EOF']);
6(wait-bad-pid) begin
7(wait-bad-pid) end
8wait-bad-pid: exit(0)
9EOF
10(wait-bad-pid) begin
11wait-bad-pid: exit(-1)
12EOF
13pass;
diff --git a/pintos-progos/tests/userprog/wait-killed.c b/pintos-progos/tests/userprog/wait-killed.c
new file mode 100644
index 0000000..6a2a6b5
--- /dev/null
+++ b/pintos-progos/tests/userprog/wait-killed.c
@@ -0,0 +1,11 @@
1/* Wait for a process that will be killed for bad behavior. */
2
3#include <syscall.h>
4#include "tests/lib.h"
5#include "tests/main.h"
6
7void
8test_main (void)
9{
10 msg ("wait(exec()) = %d", wait (exec ("child-bad")));
11}
diff --git a/pintos-progos/tests/userprog/wait-killed.ck b/pintos-progos/tests/userprog/wait-killed.ck
new file mode 100644
index 0000000..5df0e9c
--- /dev/null
+++ b/pintos-progos/tests/userprog/wait-killed.ck
@@ -0,0 +1,13 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(wait-killed) begin
7(child-bad) begin
8child-bad: exit(-1)
9(wait-killed) wait(exec()) = -1
10(wait-killed) end
11wait-killed: exit(0)
12EOF
13pass;
diff --git a/pintos-progos/tests/userprog/wait-simple.c b/pintos-progos/tests/userprog/wait-simple.c
new file mode 100644
index 0000000..d3afcf3
--- /dev/null
+++ b/pintos-progos/tests/userprog/wait-simple.c
@@ -0,0 +1,11 @@
1/* Wait for a subprocess to finish. */
2
3#include <syscall.h>
4#include "tests/lib.h"
5#include "tests/main.h"
6
7void
8test_main (void)
9{
10 msg ("wait(exec()) = %d", wait (exec ("child-simple")));
11}
diff --git a/pintos-progos/tests/userprog/wait-simple.ck b/pintos-progos/tests/userprog/wait-simple.ck
new file mode 100644
index 0000000..93dd577
--- /dev/null
+++ b/pintos-progos/tests/userprog/wait-simple.ck
@@ -0,0 +1,13 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(wait-simple) begin
7(child-simple) run
8child-simple: exit(81)
9(wait-simple) wait(exec()) = 81
10(wait-simple) end
11wait-simple: exit(0)
12EOF
13pass;
diff --git a/pintos-progos/tests/userprog/wait-twice.c b/pintos-progos/tests/userprog/wait-twice.c
new file mode 100644
index 0000000..785e684
--- /dev/null
+++ b/pintos-progos/tests/userprog/wait-twice.c
@@ -0,0 +1,15 @@
1/* Wait for a subprocess to finish, twice.
2 The first call must wait in the usual way and return the exit code.
3 The second wait call must return -1 immediately. */
4
5#include <syscall.h>
6#include "tests/lib.h"
7#include "tests/main.h"
8
9void
10test_main (void)
11{
12 pid_t child = exec ("child-simple");
13 msg ("wait(exec()) = %d", wait (child));
14 msg ("wait(exec()) = %d", wait (child));
15}
diff --git a/pintos-progos/tests/userprog/wait-twice.ck b/pintos-progos/tests/userprog/wait-twice.ck
new file mode 100644
index 0000000..6d53843
--- /dev/null
+++ b/pintos-progos/tests/userprog/wait-twice.ck
@@ -0,0 +1,14 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(wait-twice) begin
7(child-simple) run
8child-simple: exit(81)
9(wait-twice) wait(exec()) = 81
10(wait-twice) wait(exec()) = -1
11(wait-twice) end
12wait-twice: exit(0)
13EOF
14pass;
diff --git a/pintos-progos/tests/userprog/write-bad-fd.c b/pintos-progos/tests/userprog/write-bad-fd.c
new file mode 100644
index 0000000..f3b1151
--- /dev/null
+++ b/pintos-progos/tests/userprog/write-bad-fd.c
@@ -0,0 +1,20 @@
1/* Tries to write to an invalid fd,
2 which must either fail silently or terminate the process with
3 exit code -1. */
4
5#include <limits.h>
6#include <syscall.h>
7#include "tests/main.h"
8
9void
10test_main (void)
11{
12 char buf = 123;
13 write (0x01012342, &buf, 1);
14 write (7, &buf, 1);
15 write (2546, &buf, 1);
16 write (-5, &buf, 1);
17 write (-8192, &buf, 1);
18 write (INT_MIN + 1, &buf, 1);
19 write (INT_MAX - 1, &buf, 1);
20}
diff --git a/pintos-progos/tests/userprog/write-bad-fd.ck b/pintos-progos/tests/userprog/write-bad-fd.ck
new file mode 100644
index 0000000..8da7a8b
--- /dev/null
+++ b/pintos-progos/tests/userprog/write-bad-fd.ck
@@ -0,0 +1,13 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF', <<'EOF']);
6(write-bad-fd) begin
7(write-bad-fd) end
8write-bad-fd: exit(0)
9EOF
10(write-bad-fd) begin
11write-bad-fd: exit(-1)
12EOF
13pass;
diff --git a/pintos-progos/tests/userprog/write-bad-ptr.c b/pintos-progos/tests/userprog/write-bad-ptr.c
new file mode 100644
index 0000000..5336479
--- /dev/null
+++ b/pintos-progos/tests/userprog/write-bad-ptr.c
@@ -0,0 +1,16 @@
1/* Passes an invalid pointer to the write system call.
2 The process must be terminated with -1 exit code. */
3
4#include <syscall.h>
5#include "tests/lib.h"
6#include "tests/main.h"
7
8void
9test_main (void)
10{
11 int handle;
12 CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
13
14 write (handle, (char *) 0x10123420, 123);
15 fail ("should have exited with -1");
16}
diff --git a/pintos-progos/tests/userprog/write-bad-ptr.ck b/pintos-progos/tests/userprog/write-bad-ptr.ck
new file mode 100644
index 0000000..ad9f399
--- /dev/null
+++ b/pintos-progos/tests/userprog/write-bad-ptr.ck
@@ -0,0 +1,15 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF', <<'EOF']);
6(write-bad-ptr) begin
7(write-bad-ptr) open "sample.txt"
8(write-bad-ptr) end
9write-bad-ptr: exit(0)
10EOF
11(write-bad-ptr) begin
12(write-bad-ptr) open "sample.txt"
13write-bad-ptr: exit(-1)
14EOF
15pass;
diff --git a/pintos-progos/tests/userprog/write-boundary.c b/pintos-progos/tests/userprog/write-boundary.c
new file mode 100644
index 0000000..d2de1d4
--- /dev/null
+++ b/pintos-progos/tests/userprog/write-boundary.c
@@ -0,0 +1,25 @@
1/* Writes data spanning two pages in virtual address space,
2 which must succeed. */
3
4#include <string.h>
5#include <syscall.h>
6#include "tests/userprog/boundary.h"
7#include "tests/userprog/sample.inc"
8#include "tests/lib.h"
9#include "tests/main.h"
10
11void
12test_main (void)
13{
14 int handle;
15 int byte_cnt;
16 char *sample_p;
17
18 sample_p = copy_string_across_boundary (sample);
19
20 CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
21
22 byte_cnt = write (handle, sample_p, sizeof sample - 1);
23 if (byte_cnt != sizeof sample - 1)
24 fail ("write() returned %d instead of %zu", byte_cnt, sizeof sample - 1);
25}
diff --git a/pintos-progos/tests/userprog/write-boundary.ck b/pintos-progos/tests/userprog/write-boundary.ck
new file mode 100644
index 0000000..7883781
--- /dev/null
+++ b/pintos-progos/tests/userprog/write-boundary.ck
@@ -0,0 +1,11 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(write-boundary) begin
7(write-boundary) open "sample.txt"
8(write-boundary) end
9write-boundary: exit(0)
10EOF
11pass;
diff --git a/pintos-progos/tests/userprog/write-normal.c b/pintos-progos/tests/userprog/write-normal.c
new file mode 100644
index 0000000..e0297aa
--- /dev/null
+++ b/pintos-progos/tests/userprog/write-normal.c
@@ -0,0 +1,20 @@
1/* Try writing a file in the most normal way. */
2
3#include <syscall.h>
4#include "tests/userprog/sample.inc"
5#include "tests/lib.h"
6#include "tests/main.h"
7
8void
9test_main (void)
10{
11 int handle, byte_cnt;
12
13 CHECK (create ("test.txt", sizeof sample - 1), "create \"test.txt\"");
14 CHECK ((handle = open ("test.txt")) > 1, "open \"test.txt\"");
15
16 byte_cnt = write (handle, sample, sizeof sample - 1);
17 if (byte_cnt != sizeof sample - 1)
18 fail ("write() returned %d instead of %zu", byte_cnt, sizeof sample - 1);
19}
20
diff --git a/pintos-progos/tests/userprog/write-normal.ck b/pintos-progos/tests/userprog/write-normal.ck
new file mode 100644
index 0000000..9fa6024
--- /dev/null
+++ b/pintos-progos/tests/userprog/write-normal.ck
@@ -0,0 +1,12 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(write-normal) begin
7(write-normal) create "test.txt"
8(write-normal) open "test.txt"
9(write-normal) end
10write-normal: exit(0)
11EOF
12pass;
diff --git a/pintos-progos/tests/userprog/write-stdin.c b/pintos-progos/tests/userprog/write-stdin.c
new file mode 100644
index 0000000..491ea53
--- /dev/null
+++ b/pintos-progos/tests/userprog/write-stdin.c
@@ -0,0 +1,14 @@
1/* Try writing to fd 0 (stdin),
2 which may just fail or terminate the process with -1 exit
3 code. */
4
5#include <syscall.h>
6#include "tests/lib.h"
7#include "tests/main.h"
8
9void
10test_main (void)
11{
12 char buf = 123;
13 write (0, &buf, 1);
14}
diff --git a/pintos-progos/tests/userprog/write-stdin.ck b/pintos-progos/tests/userprog/write-stdin.ck
new file mode 100644
index 0000000..a6caf81
--- /dev/null
+++ b/pintos-progos/tests/userprog/write-stdin.ck
@@ -0,0 +1,13 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF', <<'EOF']);
6(write-stdin) begin
7(write-stdin) end
8write-stdin: exit(0)
9EOF
10(write-stdin) begin
11write-stdin: exit(-1)
12EOF
13pass;
diff --git a/pintos-progos/tests/userprog/write-zero.c b/pintos-progos/tests/userprog/write-zero.c
new file mode 100644
index 0000000..d8dac9b
--- /dev/null
+++ b/pintos-progos/tests/userprog/write-zero.c
@@ -0,0 +1,20 @@
1/* Try a 0-byte write, which should return 0 without writing
2 anything. */
3
4#include <syscall.h>
5#include "tests/lib.h"
6#include "tests/main.h"
7
8void
9test_main (void)
10{
11 int handle, byte_cnt;
12 char buf;
13
14 CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
15
16 buf = 123;
17 byte_cnt = write (handle, &buf, 0);
18 if (byte_cnt != 0)
19 fail("write() returned %d instead of 0", byte_cnt);
20}
diff --git a/pintos-progos/tests/userprog/write-zero.ck b/pintos-progos/tests/userprog/write-zero.ck
new file mode 100644
index 0000000..cc4cd60
--- /dev/null
+++ b/pintos-progos/tests/userprog/write-zero.ck
@@ -0,0 +1,11 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(write-zero) begin
7(write-zero) open "sample.txt"
8(write-zero) end
9write-zero: exit(0)
10EOF
11pass;