summaryrefslogtreecommitdiffstats
path: root/pintos-progos/tests/vm
diff options
context:
space:
mode:
Diffstat (limited to 'pintos-progos/tests/vm')
-rw-r--r--pintos-progos/tests/vm/Grading12
-rw-r--r--pintos-progos/tests/vm/Make.tests107
-rw-r--r--pintos-progos/tests/vm/Rubric.functionality21
-rw-r--r--pintos-progos/tests/vm/Rubric.paging8
-rw-r--r--pintos-progos/tests/vm/Rubric.robustness21
-rw-r--r--pintos-progos/tests/vm/child-inherit.c16
-rw-r--r--pintos-progos/tests/vm/child-linear.c36
-rw-r--r--pintos-progos/tests/vm/child-mm-wrt.c24
-rw-r--r--pintos-progos/tests/vm/child-qsort-mm.c25
-rw-r--r--pintos-progos/tests/vm/child-qsort.c32
-rw-r--r--pintos-progos/tests/vm/child-sort.c42
-rw-r--r--pintos-progos/tests/vm/mmap-bad-fd.c15
-rw-r--r--pintos-progos/tests/vm/mmap-bad-fd.ck15
-rw-r--r--pintos-progos/tests/vm/mmap-clean.c53
-rw-r--r--pintos-progos/tests/vm/mmap-clean.ck16
-rw-r--r--pintos-progos/tests/vm/mmap-close.c27
-rw-r--r--pintos-progos/tests/vm/mmap-close.ck11
-rw-r--r--pintos-progos/tests/vm/mmap-exit.c22
-rw-r--r--pintos-progos/tests/vm/mmap-exit.ck17
-rw-r--r--pintos-progos/tests/vm/mmap-inherit.c32
-rw-r--r--pintos-progos/tests/vm/mmap-inherit.ck16
-rw-r--r--pintos-progos/tests/vm/mmap-lazy-seq.c52
-rw-r--r--pintos-progos/tests/vm/mmap-lazy-seq.ck27
-rw-r--r--pintos-progos/tests/vm/mmap-misalign.c16
-rw-r--r--pintos-progos/tests/vm/mmap-misalign.ck11
-rw-r--r--pintos-progos/tests/vm/mmap-null.c15
-rw-r--r--pintos-progos/tests/vm/mmap-null.ck11
-rw-r--r--pintos-progos/tests/vm/mmap-over-code.c19
-rw-r--r--pintos-progos/tests/vm/mmap-over-code.ck11
-rw-r--r--pintos-progos/tests/vm/mmap-over-data.c21
-rw-r--r--pintos-progos/tests/vm/mmap-over-data.ck11
-rw-r--r--pintos-progos/tests/vm/mmap-over-stk.c19
-rw-r--r--pintos-progos/tests/vm/mmap-over-stk.ck11
-rw-r--r--pintos-progos/tests/vm/mmap-overlap.c20
-rw-r--r--pintos-progos/tests/vm/mmap-overlap.ck13
-rw-r--r--pintos-progos/tests/vm/mmap-read.c32
-rw-r--r--pintos-progos/tests/vm/mmap-read.ck11
-rw-r--r--pintos-progos/tests/vm/mmap-remove.c43
-rw-r--r--pintos-progos/tests/vm/mmap-remove.ck14
-rw-r--r--pintos-progos/tests/vm/mmap-shuffle.c38
-rw-r--r--pintos-progos/tests/vm/mmap-shuffle.ck47
-rw-r--r--pintos-progos/tests/vm/mmap-twice.c28
-rw-r--r--pintos-progos/tests/vm/mmap-twice.ck15
-rw-r--r--pintos-progos/tests/vm/mmap-unmap.c23
-rw-r--r--pintos-progos/tests/vm/mmap-unmap.ck7
-rw-r--r--pintos-progos/tests/vm/mmap-write.c32
-rw-r--r--pintos-progos/tests/vm/mmap-write.ck13
-rw-r--r--pintos-progos/tests/vm/mmap-zero.c27
-rw-r--r--pintos-progos/tests/vm/mmap-zero.ck12
-rw-r--r--pintos-progos/tests/vm/page-linear.c44
-rw-r--r--pintos-progos/tests/vm/page-linear.ck14
-rw-r--r--pintos-progos/tests/vm/page-merge-mm.c8
-rw-r--r--pintos-progos/tests/vm/page-merge-mm.ck29
-rw-r--r--pintos-progos/tests/vm/page-merge-par.c8
-rw-r--r--pintos-progos/tests/vm/page-merge-par.ck29
-rw-r--r--pintos-progos/tests/vm/page-merge-seq.c137
-rw-r--r--pintos-progos/tests/vm/page-merge-seq.ck29
-rw-r--r--pintos-progos/tests/vm/page-merge-stk.c8
-rw-r--r--pintos-progos/tests/vm/page-merge-stk.ck29
-rw-r--r--pintos-progos/tests/vm/page-parallel.c21
-rw-r--r--pintos-progos/tests/vm/page-parallel.ck17
-rw-r--r--pintos-progos/tests/vm/page-shuffle.c30
-rw-r--r--pintos-progos/tests/vm/page-shuffle.ck44
-rw-r--r--pintos-progos/tests/vm/parallel-merge.c149
-rw-r--r--pintos-progos/tests/vm/parallel-merge.h6
-rw-r--r--pintos-progos/tests/vm/process_death.pm22
-rw-r--r--pintos-progos/tests/vm/pt-bad-addr.c11
-rw-r--r--pintos-progos/tests/vm/pt-bad-addr.ck7
-rw-r--r--pintos-progos/tests/vm/pt-bad-read.c16
-rw-r--r--pintos-progos/tests/vm/pt-bad-read.ck10
-rw-r--r--pintos-progos/tests/vm/pt-big-stk-obj.c20
-rw-r--r--pintos-progos/tests/vm/pt-big-stk-obj.ck10
-rw-r--r--pintos-progos/tests/vm/pt-grow-bad.c14
-rw-r--r--pintos-progos/tests/vm/pt-grow-bad.ck9
-rw-r--r--pintos-progos/tests/vm/pt-grow-pusha.c20
-rw-r--r--pintos-progos/tests/vm/pt-grow-pusha.ck9
-rw-r--r--pintos-progos/tests/vm/pt-grow-stack.c20
-rw-r--r--pintos-progos/tests/vm/pt-grow-stack.ck10
-rw-r--r--pintos-progos/tests/vm/pt-grow-stk-sc.c32
-rw-r--r--pintos-progos/tests/vm/pt-grow-stk-sc.ck15
-rw-r--r--pintos-progos/tests/vm/pt-write-code-2.c15
-rw-r--r--pintos-progos/tests/vm/pt-write-code.c12
-rw-r--r--pintos-progos/tests/vm/pt-write-code.ck7
-rw-r--r--pintos-progos/tests/vm/pt-write-code2.ck10
-rw-r--r--pintos-progos/tests/vm/qsort.c136
-rw-r--r--pintos-progos/tests/vm/qsort.h8
-rw-r--r--pintos-progos/tests/vm/sample.inc19
-rw-r--r--pintos-progos/tests/vm/sample.txt17
88 files changed, 2218 insertions, 0 deletions
diff --git a/pintos-progos/tests/vm/Grading b/pintos-progos/tests/vm/Grading
new file mode 100644
index 0000000..f0c2c13
--- /dev/null
+++ b/pintos-progos/tests/vm/Grading
@@ -0,0 +1,12 @@
1# Percentage of the testing point total designated for each set of
2# tests.
3
4# This project is primarily about virtual memory, but all the previous
5# functionality should work too, and it's easy to screw it up, thus
6# the equal weight placed on each.
7
850% tests/vm/Rubric.functionality
915% tests/vm/Rubric.robustness
1010% tests/userprog/Rubric.functionality
115% tests/userprog/Rubric.robustness
1220% tests/filesys/base/Rubric
diff --git a/pintos-progos/tests/vm/Make.tests b/pintos-progos/tests/vm/Make.tests
new file mode 100644
index 0000000..0307ccc
--- /dev/null
+++ b/pintos-progos/tests/vm/Make.tests
@@ -0,0 +1,107 @@
1# -*- makefile -*-
2
3tests/vm_TESTS = $(addprefix tests/vm/,pt-grow-stack pt-grow-pusha \
4pt-grow-bad pt-big-stk-obj pt-bad-addr pt-bad-read pt-write-code \
5pt-write-code2 pt-grow-stk-sc mmap-read \
6mmap-close mmap-unmap mmap-overlap mmap-twice mmap-write mmap-exit \
7mmap-shuffle mmap-bad-fd mmap-clean mmap-inherit mmap-misalign \
8mmap-null mmap-over-code mmap-over-data mmap-over-stk mmap-remove \
9mmap-zero mmap-lazy-seq)
10
11# Deactivated
12PAGE_TESTS=page-linear page-parallel page-merge-seq \
13page-merge-par page-merge-stk page-merge-mm page-shuffle
14
15tests/vm_PROGS = $(tests/vm_TESTS) $(addprefix tests/vm/,child-linear \
16child-sort child-qsort child-qsort-mm child-mm-wrt child-inherit)
17
18tests/vm/pt-grow-stack_SRC = tests/vm/pt-grow-stack.c tests/arc4.c \
19tests/cksum.c tests/lib.c tests/main.c
20tests/vm/pt-grow-pusha_SRC = tests/vm/pt-grow-pusha.c tests/lib.c \
21tests/main.c
22tests/vm/pt-grow-bad_SRC = tests/vm/pt-grow-bad.c tests/lib.c tests/main.c
23tests/vm/pt-big-stk-obj_SRC = tests/vm/pt-big-stk-obj.c tests/arc4.c \
24tests/cksum.c tests/lib.c tests/main.c
25tests/vm/pt-bad-addr_SRC = tests/vm/pt-bad-addr.c tests/lib.c tests/main.c
26tests/vm/pt-bad-read_SRC = tests/vm/pt-bad-read.c tests/lib.c tests/main.c
27tests/vm/pt-write-code_SRC = tests/vm/pt-write-code.c tests/lib.c tests/main.c
28tests/vm/pt-write-code2_SRC = tests/vm/pt-write-code-2.c tests/lib.c tests/main.c
29tests/vm/pt-grow-stk-sc_SRC = tests/vm/pt-grow-stk-sc.c tests/lib.c tests/main.c
30tests/vm/page-linear_SRC = tests/vm/page-linear.c tests/arc4.c \
31tests/lib.c tests/main.c
32tests/vm/page-parallel_SRC = tests/vm/page-parallel.c tests/lib.c tests/main.c
33tests/vm/page-merge-seq_SRC = tests/vm/page-merge-seq.c tests/arc4.c \
34tests/lib.c tests/main.c
35tests/vm/page-merge-par_SRC = tests/vm/page-merge-par.c \
36tests/vm/parallel-merge.c tests/arc4.c tests/lib.c tests/main.c
37tests/vm/page-merge-stk_SRC = tests/vm/page-merge-stk.c \
38tests/vm/parallel-merge.c tests/arc4.c tests/lib.c tests/main.c
39tests/vm/page-merge-mm_SRC = tests/vm/page-merge-mm.c \
40tests/vm/parallel-merge.c tests/arc4.c tests/lib.c tests/main.c
41tests/vm/page-shuffle_SRC = tests/vm/page-shuffle.c tests/arc4.c \
42tests/cksum.c tests/lib.c tests/main.c
43tests/vm/mmap-read_SRC = tests/vm/mmap-read.c tests/lib.c tests/main.c
44tests/vm/mmap-close_SRC = tests/vm/mmap-close.c tests/lib.c tests/main.c
45tests/vm/mmap-unmap_SRC = tests/vm/mmap-unmap.c tests/lib.c tests/main.c
46tests/vm/mmap-overlap_SRC = tests/vm/mmap-overlap.c tests/lib.c tests/main.c
47tests/vm/mmap-twice_SRC = tests/vm/mmap-twice.c tests/lib.c tests/main.c
48tests/vm/mmap-write_SRC = tests/vm/mmap-write.c tests/lib.c tests/main.c
49tests/vm/mmap-lazy-seq_SRC = tests/vm/mmap-lazy-seq.c tests/lib.c tests/main.c
50tests/vm/mmap-exit_SRC = tests/vm/mmap-exit.c tests/lib.c tests/main.c
51tests/vm/mmap-shuffle_SRC = tests/vm/mmap-shuffle.c tests/arc4.c \
52tests/cksum.c tests/lib.c tests/main.c
53tests/vm/mmap-bad-fd_SRC = tests/vm/mmap-bad-fd.c tests/lib.c tests/main.c
54tests/vm/mmap-clean_SRC = tests/vm/mmap-clean.c tests/lib.c tests/main.c
55tests/vm/mmap-inherit_SRC = tests/vm/mmap-inherit.c tests/lib.c tests/main.c
56tests/vm/mmap-misalign_SRC = tests/vm/mmap-misalign.c tests/lib.c \
57tests/main.c
58tests/vm/mmap-null_SRC = tests/vm/mmap-null.c tests/lib.c tests/main.c
59tests/vm/mmap-over-code_SRC = tests/vm/mmap-over-code.c tests/lib.c \
60tests/main.c
61tests/vm/mmap-over-data_SRC = tests/vm/mmap-over-data.c tests/lib.c \
62tests/main.c
63tests/vm/mmap-over-stk_SRC = tests/vm/mmap-over-stk.c tests/lib.c tests/main.c
64tests/vm/mmap-remove_SRC = tests/vm/mmap-remove.c tests/lib.c tests/main.c
65tests/vm/mmap-zero_SRC = tests/vm/mmap-zero.c tests/lib.c tests/main.c
66
67tests/vm/child-linear_SRC = tests/vm/child-linear.c tests/arc4.c tests/lib.c
68tests/vm/child-qsort_SRC = tests/vm/child-qsort.c tests/vm/qsort.c tests/lib.c
69tests/vm/child-qsort-mm_SRC = tests/vm/child-qsort-mm.c tests/vm/qsort.c \
70tests/lib.c
71tests/vm/child-sort_SRC = tests/vm/child-sort.c tests/lib.c
72tests/vm/child-mm-wrt_SRC = tests/vm/child-mm-wrt.c tests/lib.c tests/main.c
73tests/vm/child-inherit_SRC = tests/vm/child-inherit.c tests/lib.c tests/main.c
74
75tests/vm/pt-bad-read_PUTFILES = tests/vm/sample.txt
76tests/vm/pt-write-code2_PUTFILES = tests/vm/sample.txt
77tests/vm/mmap-close_PUTFILES = tests/vm/sample.txt
78tests/vm/mmap-read_PUTFILES = tests/vm/sample.txt
79tests/vm/mmap-unmap_PUTFILES = tests/vm/sample.txt
80tests/vm/mmap-twice_PUTFILES = tests/vm/sample.txt
81tests/vm/mmap-overlap_PUTFILES = tests/vm/zeros
82tests/vm/mmap-exit_PUTFILES = tests/vm/child-mm-wrt
83tests/vm/page-parallel_PUTFILES = tests/vm/child-linear
84tests/vm/page-merge-seq_PUTFILES = tests/vm/child-sort
85tests/vm/page-merge-par_PUTFILES = tests/vm/child-sort
86tests/vm/page-merge-stk_PUTFILES = tests/vm/child-qsort
87tests/vm/page-merge-mm_PUTFILES = tests/vm/child-qsort-mm
88tests/vm/mmap-clean_PUTFILES = tests/vm/sample.txt
89tests/vm/mmap-inherit_PUTFILES = tests/vm/sample.txt tests/vm/child-inherit
90tests/vm/mmap-misalign_PUTFILES = tests/vm/sample.txt
91tests/vm/mmap-null_PUTFILES = tests/vm/sample.txt
92tests/vm/mmap-over-code_PUTFILES = tests/vm/sample.txt
93tests/vm/mmap-over-data_PUTFILES = tests/vm/sample.txt
94tests/vm/mmap-over-stk_PUTFILES = tests/vm/sample.txt
95tests/vm/mmap-remove_PUTFILES = tests/vm/sample.txt
96
97tests/vm/page-linear.output: TIMEOUT = 300
98tests/vm/page-shuffle.output: TIMEOUT = 600
99tests/vm/mmap-shuffle.output: TIMEOUT = 600
100tests/vm/page-merge-seq.output: TIMEOUT = 600
101tests/vm/page-merge-par.output: TIMEOUT = 600
102
103tests/vm/zeros:
104 dd if=/dev/zero of=$@ bs=1024 count=6
105
106clean::
107 rm -f tests/vm/zeros
diff --git a/pintos-progos/tests/vm/Rubric.functionality b/pintos-progos/tests/vm/Rubric.functionality
new file mode 100644
index 0000000..ede0221
--- /dev/null
+++ b/pintos-progos/tests/vm/Rubric.functionality
@@ -0,0 +1,21 @@
1Functionality of virtual memory subsystem:
2- Test stack growth.
33 pt-grow-stack
43 pt-grow-stk-sc
53 pt-big-stk-obj
63 pt-grow-pusha
7
8- Test "mmap" system call.
92 mmap-read
102 mmap-write
112 mmap-shuffle
12
132 mmap-twice
14
152 mmap-unmap
161 mmap-exit
17
183 mmap-clean
19
202 mmap-close
212 mmap-remove
diff --git a/pintos-progos/tests/vm/Rubric.paging b/pintos-progos/tests/vm/Rubric.paging
new file mode 100644
index 0000000..cf1d871
--- /dev/null
+++ b/pintos-progos/tests/vm/Rubric.paging
@@ -0,0 +1,8 @@
1- Test paging behavior.
23 page-linear
33 page-parallel
43 page-shuffle
54 page-merge-seq
64 page-merge-par
74 page-merge-mm
84 page-merge-stk
diff --git a/pintos-progos/tests/vm/Rubric.robustness b/pintos-progos/tests/vm/Rubric.robustness
new file mode 100644
index 0000000..eca0af4
--- /dev/null
+++ b/pintos-progos/tests/vm/Rubric.robustness
@@ -0,0 +1,21 @@
1Robustness of virtual memory subsystem:
2- Test robustness of page table support.
32 pt-bad-addr
43 pt-bad-read
52 pt-write-code
63 pt-write-code2
74 pt-grow-bad
8
9- Test robustness of "mmap" system call.
101 mmap-bad-fd
111 mmap-inherit
121 mmap-null
131 mmap-zero
14
152 mmap-misalign
16
172 mmap-over-code
182 mmap-over-data
192 mmap-over-stk
202 mmap-overlap
214 mmap-lazy-seq
diff --git a/pintos-progos/tests/vm/child-inherit.c b/pintos-progos/tests/vm/child-inherit.c
new file mode 100644
index 0000000..d3186a1
--- /dev/null
+++ b/pintos-progos/tests/vm/child-inherit.c
@@ -0,0 +1,16 @@
1/* Child process for mmap-inherit test.
2 Tries to write to a mapping present in the parent.
3 The process must be terminated with -1 exit code. */
4
5#include <string.h>
6#include "tests/vm/sample.inc"
7#include "tests/lib.h"
8#include "tests/main.h"
9
10void
11test_main (void)
12{
13 memset ((char *) 0x54321000, 0, 4096);
14 fail ("child can modify parent's memory mappings");
15}
16
diff --git a/pintos-progos/tests/vm/child-linear.c b/pintos-progos/tests/vm/child-linear.c
new file mode 100644
index 0000000..eca3e3f
--- /dev/null
+++ b/pintos-progos/tests/vm/child-linear.c
@@ -0,0 +1,36 @@
1/* Child process of page-parallel.
2 Encrypts 1 MB of zeros, then decrypts it, and ensures that
3 the zeros are back. */
4
5#include <string.h>
6#include "tests/arc4.h"
7#include "tests/lib.h"
8#include "tests/main.h"
9
10const char *test_name = "child-linear";
11
12#define SIZE (1024 * 1024)
13static char buf[SIZE];
14
15int
16main (int argc, char *argv[])
17{
18 const char *key = argv[argc - 1];
19 struct arc4 arc4;
20 size_t i;
21
22 /* Encrypt zeros. */
23 arc4_init (&arc4, key, strlen (key));
24 arc4_crypt (&arc4, buf, SIZE);
25
26 /* Decrypt back to zeros. */
27 arc4_init (&arc4, key, strlen (key));
28 arc4_crypt (&arc4, buf, SIZE);
29
30 /* Check that it's all zeros. */
31 for (i = 0; i < SIZE; i++)
32 if (buf[i] != '\0')
33 fail ("byte %zu != 0", i);
34
35 return 0x42;
36}
diff --git a/pintos-progos/tests/vm/child-mm-wrt.c b/pintos-progos/tests/vm/child-mm-wrt.c
new file mode 100644
index 0000000..8419788
--- /dev/null
+++ b/pintos-progos/tests/vm/child-mm-wrt.c
@@ -0,0 +1,24 @@
1/* Child process of mmap-exit.
2 Mmaps a file and writes to it via the mmap'ing, then exits
3 without calling munmap. The data in the mapped region must be
4 written out at program termination. */
5
6#include <string.h>
7#include <syscall.h>
8#include "tests/vm/sample.inc"
9#include "tests/lib.h"
10#include "tests/main.h"
11
12#define ACTUAL ((void *) 0x10000000)
13
14void
15test_main (void)
16{
17 int handle;
18
19 CHECK (create ("sample.txt", sizeof sample), "create \"sample.txt\"");
20 CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
21 CHECK (mmap (handle, ACTUAL) != MAP_FAILED, "mmap \"sample.txt\"");
22 memcpy (ACTUAL, sample, sizeof sample);
23}
24
diff --git a/pintos-progos/tests/vm/child-qsort-mm.c b/pintos-progos/tests/vm/child-qsort-mm.c
new file mode 100644
index 0000000..db45499
--- /dev/null
+++ b/pintos-progos/tests/vm/child-qsort-mm.c
@@ -0,0 +1,25 @@
1/* Mmaps a 128 kB file "sorts" the bytes in it, using quick sort,
2 a multi-pass divide and conquer algorithm. */
3
4#include <debug.h>
5#include <syscall.h>
6#include "tests/lib.h"
7#include "tests/main.h"
8#include "tests/vm/qsort.h"
9
10const char *test_name = "child-qsort-mm";
11
12int
13main (int argc UNUSED, char *argv[])
14{
15 int handle;
16 unsigned char *p = (unsigned char *) 0x10000000;
17
18 quiet = true;
19
20 CHECK ((handle = open (argv[1])) > 1, "open \"%s\"", argv[1]);
21 CHECK (mmap (handle, p) != MAP_FAILED, "mmap \"%s\"", argv[1]);
22 qsort_bytes (p, 1024 * 128);
23
24 return 80;
25}
diff --git a/pintos-progos/tests/vm/child-qsort.c b/pintos-progos/tests/vm/child-qsort.c
new file mode 100644
index 0000000..355f4eb
--- /dev/null
+++ b/pintos-progos/tests/vm/child-qsort.c
@@ -0,0 +1,32 @@
1/* Reads a 128 kB file onto the stack and "sorts" the bytes in
2 it, using quick sort, a multi-pass divide and conquer
3 algorithm. The sorted data is written back to the same file
4 in-place. */
5
6#include <debug.h>
7#include <syscall.h>
8#include "tests/lib.h"
9#include "tests/main.h"
10#include "tests/vm/qsort.h"
11
12const char *test_name = "child-qsort";
13
14int
15main (int argc UNUSED, char *argv[])
16{
17 int handle;
18 unsigned char buf[128 * 1024];
19 size_t size;
20
21 quiet = true;
22
23 CHECK ((handle = open (argv[1])) > 1, "open \"%s\"", argv[1]);
24
25 size = read (handle, buf, sizeof buf);
26 qsort_bytes (buf, sizeof buf);
27 seek (handle, 0);
28 write (handle, buf, size);
29 close (handle);
30
31 return 72;
32}
diff --git a/pintos-progos/tests/vm/child-sort.c b/pintos-progos/tests/vm/child-sort.c
new file mode 100644
index 0000000..dff2c77
--- /dev/null
+++ b/pintos-progos/tests/vm/child-sort.c
@@ -0,0 +1,42 @@
1/* Reads a 128 kB file into static data and "sorts" the bytes in
2 it, using counting sort, a single-pass algorithm. The sorted
3 data is written back to the same file in-place. */
4
5#include <debug.h>
6#include <syscall.h>
7#include "tests/lib.h"
8#include "tests/main.h"
9
10const char *test_name = "child-sort";
11
12unsigned char buf[128 * 1024];
13size_t histogram[256];
14
15int
16main (int argc UNUSED, char *argv[])
17{
18 int handle;
19 unsigned char *p;
20 size_t size;
21 size_t i;
22
23 quiet = true;
24
25 CHECK ((handle = open (argv[1])) > 1, "open \"%s\"", argv[1]);
26
27 size = read (handle, buf, sizeof buf);
28 for (i = 0; i < size; i++)
29 histogram[buf[i]]++;
30 p = buf;
31 for (i = 0; i < sizeof histogram / sizeof *histogram; i++)
32 {
33 size_t j = histogram[i];
34 while (j-- > 0)
35 *p++ = i;
36 }
37 seek (handle, 0);
38 write (handle, buf, size);
39 close (handle);
40
41 return 123;
42}
diff --git a/pintos-progos/tests/vm/mmap-bad-fd.c b/pintos-progos/tests/vm/mmap-bad-fd.c
new file mode 100644
index 0000000..76a7b50
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-bad-fd.c
@@ -0,0 +1,15 @@
1/* Tries to mmap an invalid fd,
2 which must either fail silently or terminate the process with
3 exit code -1. */
4
5#include <syscall.h>
6#include "tests/lib.h"
7#include "tests/main.h"
8
9void
10test_main (void)
11{
12 CHECK (mmap (0x5678, (void *) 0x10000000) == MAP_FAILED,
13 "try to mmap invalid fd");
14}
15
diff --git a/pintos-progos/tests/vm/mmap-bad-fd.ck b/pintos-progos/tests/vm/mmap-bad-fd.ck
new file mode 100644
index 0000000..f3f58d5
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-bad-fd.ck
@@ -0,0 +1,15 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF', <<'EOF']);
6(mmap-bad-fd) begin
7(mmap-bad-fd) try to mmap invalid fd
8(mmap-bad-fd) end
9mmap-bad-fd: exit(0)
10EOF
11(mmap-bad-fd) begin
12(mmap-bad-fd) try to mmap invalid fd
13mmap-bad-fd: exit(-1)
14EOF
15pass;
diff --git a/pintos-progos/tests/vm/mmap-clean.c b/pintos-progos/tests/vm/mmap-clean.c
new file mode 100644
index 0000000..ea1dc9c
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-clean.c
@@ -0,0 +1,53 @@
1/* Verifies that mmap'd regions are only written back on munmap
2 if the data was actually modified in memory. */
3
4#include <string.h>
5#include <syscall.h>
6#include "tests/vm/sample.inc"
7#include "tests/lib.h"
8#include "tests/main.h"
9
10void
11test_main (void)
12{
13 static const char overwrite[] = "Now is the time for all good...";
14 static char buffer[sizeof sample - 1];
15 char *actual = (char *) 0x54321000;
16 int handle;
17 mapid_t map;
18
19 /* Open file, map, verify data. */
20 CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
21 CHECK ((map = mmap (handle, actual)) != MAP_FAILED, "mmap \"sample.txt\"");
22 if (memcmp (actual, sample, strlen (sample)))
23 fail ("read of mmap'd file reported bad data");
24
25 /* Modify file. */
26 CHECK (write (handle, overwrite, strlen (overwrite))
27 == (int) strlen (overwrite),
28 "write \"sample.txt\"");
29
30 /* Close mapping. Data should not be written back, because we
31 didn't modify it via the mapping. */
32 msg ("munmap \"sample.txt\"");
33 munmap (map);
34
35 /* Read file back. */
36 msg ("seek \"sample.txt\"");
37 seek (handle, 0);
38 CHECK (read (handle, buffer, sizeof buffer) == sizeof buffer,
39 "read \"sample.txt\"");
40
41 /* Verify that file overwrite worked. */
42 if (memcmp (buffer, overwrite, strlen (overwrite))
43 || memcmp (buffer + strlen (overwrite), sample + strlen (overwrite),
44 strlen (sample) - strlen (overwrite)))
45 {
46 if (!memcmp (buffer, sample, strlen (sample)))
47 fail ("munmap wrote back clean page");
48 else
49 fail ("read surprising data from file");
50 }
51 else
52 msg ("file change was retained after munmap");
53}
diff --git a/pintos-progos/tests/vm/mmap-clean.ck b/pintos-progos/tests/vm/mmap-clean.ck
new file mode 100644
index 0000000..1666d6c
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-clean.ck
@@ -0,0 +1,16 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(mmap-clean) begin
7(mmap-clean) open "sample.txt"
8(mmap-clean) mmap "sample.txt"
9(mmap-clean) write "sample.txt"
10(mmap-clean) munmap "sample.txt"
11(mmap-clean) seek "sample.txt"
12(mmap-clean) read "sample.txt"
13(mmap-clean) file change was retained after munmap
14(mmap-clean) end
15EOF
16pass;
diff --git a/pintos-progos/tests/vm/mmap-close.c b/pintos-progos/tests/vm/mmap-close.c
new file mode 100644
index 0000000..d016ee3
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-close.c
@@ -0,0 +1,27 @@
1/* Verifies that memory mappings persist after file close. */
2
3#include <string.h>
4#include <syscall.h>
5#include "tests/vm/sample.inc"
6#include "tests/arc4.h"
7#include "tests/lib.h"
8#include "tests/main.h"
9
10#define ACTUAL ((void *) 0x10000000)
11
12void
13test_main (void)
14{
15 int handle;
16 mapid_t map;
17
18 CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
19 CHECK ((map = mmap (handle, ACTUAL)) != MAP_FAILED, "mmap \"sample.txt\"");
20
21 close (handle);
22
23 if (memcmp (ACTUAL, sample, strlen (sample)))
24 fail ("read of mmap'd file reported bad data");
25
26 munmap (map);
27}
diff --git a/pintos-progos/tests/vm/mmap-close.ck b/pintos-progos/tests/vm/mmap-close.ck
new file mode 100644
index 0000000..d15e41a
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-close.ck
@@ -0,0 +1,11 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(mmap-close) begin
7(mmap-close) open "sample.txt"
8(mmap-close) mmap "sample.txt"
9(mmap-close) end
10EOF
11pass;
diff --git a/pintos-progos/tests/vm/mmap-exit.c b/pintos-progos/tests/vm/mmap-exit.c
new file mode 100644
index 0000000..7a2278a
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-exit.c
@@ -0,0 +1,22 @@
1/* Executes child-mm-wrt and verifies that the writes that should
2 have occurred really did. */
3
4#include <syscall.h>
5#include "tests/vm/sample.inc"
6#include "tests/lib.h"
7#include "tests/main.h"
8
9void
10test_main (void)
11{
12 pid_t child;
13
14 /* Make child write file. */
15 quiet = true;
16 CHECK ((child = exec ("child-mm-wrt")) != -1, "exec \"child-mm-wrt\"");
17 CHECK (wait (child) == 0, "wait for child (should return 0)");
18 quiet = false;
19
20 /* Check file contents. */
21 check_file ("sample.txt", sample, sizeof sample);
22}
diff --git a/pintos-progos/tests/vm/mmap-exit.ck b/pintos-progos/tests/vm/mmap-exit.ck
new file mode 100644
index 0000000..457d34a
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-exit.ck
@@ -0,0 +1,17 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(mmap-exit) begin
7(child-mm-wrt) begin
8(child-mm-wrt) create "sample.txt"
9(child-mm-wrt) open "sample.txt"
10(child-mm-wrt) mmap "sample.txt"
11(child-mm-wrt) end
12(mmap-exit) open "sample.txt" for verification
13(mmap-exit) verified contents of "sample.txt"
14(mmap-exit) close "sample.txt"
15(mmap-exit) end
16EOF
17pass;
diff --git a/pintos-progos/tests/vm/mmap-inherit.c b/pintos-progos/tests/vm/mmap-inherit.c
new file mode 100644
index 0000000..7fa9607
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-inherit.c
@@ -0,0 +1,32 @@
1/* Maps a file into memory and runs child-inherit to verify that
2 mappings are not inherited. */
3
4#include <string.h>
5#include <syscall.h>
6#include "tests/vm/sample.inc"
7#include "tests/lib.h"
8#include "tests/main.h"
9
10void
11test_main (void)
12{
13 char *actual = (char *) 0x54321000;
14 int handle;
15 pid_t child;
16
17 /* Open file, map, verify data. */
18 CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
19 CHECK (mmap (handle, actual) != MAP_FAILED, "mmap \"sample.txt\"");
20 if (memcmp (actual, sample, strlen (sample)))
21 fail ("read of mmap'd file reported bad data");
22
23 /* Spawn child and wait. */
24 CHECK ((child = exec ("child-inherit")) != -1, "exec \"child-inherit\"");
25 quiet = true;
26 CHECK (wait (child) == -1, "wait for child (should return -1)");
27 quiet = false;
28
29 /* Verify data again. */
30 CHECK (!memcmp (actual, sample, strlen (sample)),
31 "checking that mmap'd file still has same data");
32}
diff --git a/pintos-progos/tests/vm/mmap-inherit.ck b/pintos-progos/tests/vm/mmap-inherit.ck
new file mode 100644
index 0000000..c54638a
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-inherit.ck
@@ -0,0 +1,16 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']);
6(mmap-inherit) begin
7(mmap-inherit) open "sample.txt"
8(mmap-inherit) mmap "sample.txt"
9(mmap-inherit) exec "child-inherit"
10(child-inherit) begin
11child-inherit: exit(-1)
12(mmap-inherit) checking that mmap'd file still has same data
13(mmap-inherit) end
14mmap-inherit: exit(0)
15EOF
16pass;
diff --git a/pintos-progos/tests/vm/mmap-lazy-seq.c b/pintos-progos/tests/vm/mmap-lazy-seq.c
new file mode 100644
index 0000000..b8f07bd
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-lazy-seq.c
@@ -0,0 +1,52 @@
1/* Create a large file, and mmap it several times, writing to
2 different pages. Then unmaps the file, and reads the data back
3 to verify */
4
5#include <string.h>
6#include <syscall.h>
7#include "tests/vm/sample.inc"
8#include "tests/lib.h"
9#include "tests/main.h"
10
11/* Offset needs to be larger or equal to page size */
12#define OFFSET(i) (8192*(i))
13/* Number of times file is mmapped */
14#define N (8)
15/* Size of file */
16#define FILE_SIZE (1024*1024)
17/* Address for mmap */
18#define ACTUAL(i) ((void *) (0x10000000 + (i)*FILE_SIZE))
19
20
21void
22test_main (void)
23{
24 int i;
25 int handle;
26 mapid_t map[N];
27 char buf[1024];
28 /* create file */
29 CHECK (create ("sample.txt", FILE_SIZE), "create \"sample.txt\"");
30 CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
31 /* mmap */
32 for (i = 0; i < N; i++) {
33 CHECK ((map[i] = mmap (handle, ACTUAL(i))) != MAP_FAILED, "mmap \"sample.txt\"");
34 }
35 /* write */
36 for (i = 0; i < N; i++) {
37 memcpy (buf, ACTUAL(i)+OFFSET(i+N), 1024); /* not checked */
38 memcpy (ACTUAL(i)+OFFSET(i), sample, strlen (sample));
39 }
40 /* munmap */
41 for (i = 0; i < N; i++) {
42 munmap (map[i]);
43 }
44 /* Read back via read(). */
45 for (i = 0; i < N; i++) {
46 seek (handle, OFFSET(i));
47 read (handle, buf, strlen (sample));
48 CHECK (!memcmp (buf, sample, strlen (sample)),
49 "compare read data against written data");
50 }
51 close (handle);
52}
diff --git a/pintos-progos/tests/vm/mmap-lazy-seq.ck b/pintos-progos/tests/vm/mmap-lazy-seq.ck
new file mode 100644
index 0000000..dd0e240
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-lazy-seq.ck
@@ -0,0 +1,27 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(mmap-lazy-seq) begin
7(mmap-lazy-seq) create "sample.txt"
8(mmap-lazy-seq) open "sample.txt"
9(mmap-lazy-seq) mmap "sample.txt"
10(mmap-lazy-seq) mmap "sample.txt"
11(mmap-lazy-seq) mmap "sample.txt"
12(mmap-lazy-seq) mmap "sample.txt"
13(mmap-lazy-seq) mmap "sample.txt"
14(mmap-lazy-seq) mmap "sample.txt"
15(mmap-lazy-seq) mmap "sample.txt"
16(mmap-lazy-seq) mmap "sample.txt"
17(mmap-lazy-seq) compare read data against written data
18(mmap-lazy-seq) compare read data against written data
19(mmap-lazy-seq) compare read data against written data
20(mmap-lazy-seq) compare read data against written data
21(mmap-lazy-seq) compare read data against written data
22(mmap-lazy-seq) compare read data against written data
23(mmap-lazy-seq) compare read data against written data
24(mmap-lazy-seq) compare read data against written data
25(mmap-lazy-seq) end
26EOF
27pass;
diff --git a/pintos-progos/tests/vm/mmap-misalign.c b/pintos-progos/tests/vm/mmap-misalign.c
new file mode 100644
index 0000000..34141a9
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-misalign.c
@@ -0,0 +1,16 @@
1/* Verifies that misaligned memory mappings are disallowed. */
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
12 CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
13 CHECK (mmap (handle, (void *) 0x10001234) == MAP_FAILED,
14 "try to mmap at misaligned address");
15}
16
diff --git a/pintos-progos/tests/vm/mmap-misalign.ck b/pintos-progos/tests/vm/mmap-misalign.ck
new file mode 100644
index 0000000..145a2e8
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-misalign.ck
@@ -0,0 +1,11 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(mmap-misalign) begin
7(mmap-misalign) open "sample.txt"
8(mmap-misalign) try to mmap at misaligned address
9(mmap-misalign) end
10EOF
11pass;
diff --git a/pintos-progos/tests/vm/mmap-null.c b/pintos-progos/tests/vm/mmap-null.c
new file mode 100644
index 0000000..f8ef075
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-null.c
@@ -0,0 +1,15 @@
1/* Verifies that memory mappings at address 0 are disallowed. */
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
12 CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
13 CHECK (mmap (handle, NULL) == MAP_FAILED, "try to mmap at address 0");
14}
15
diff --git a/pintos-progos/tests/vm/mmap-null.ck b/pintos-progos/tests/vm/mmap-null.ck
new file mode 100644
index 0000000..aacdd65
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-null.ck
@@ -0,0 +1,11 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(mmap-null) begin
7(mmap-null) open "sample.txt"
8(mmap-null) try to mmap at address 0
9(mmap-null) end
10EOF
11pass;
diff --git a/pintos-progos/tests/vm/mmap-over-code.c b/pintos-progos/tests/vm/mmap-over-code.c
new file mode 100644
index 0000000..d3619a3
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-over-code.c
@@ -0,0 +1,19 @@
1/* Verifies that mapping over the code segment is disallowed. */
2
3#include <stdint.h>
4#include <round.h>
5#include <syscall.h>
6#include "tests/lib.h"
7#include "tests/main.h"
8
9void
10test_main (void)
11{
12 uintptr_t test_main_page = ROUND_DOWN ((uintptr_t) test_main, 4096);
13 int handle;
14
15 CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
16 CHECK (mmap (handle, (void *) test_main_page) == MAP_FAILED,
17 "try to mmap over code segment");
18}
19
diff --git a/pintos-progos/tests/vm/mmap-over-code.ck b/pintos-progos/tests/vm/mmap-over-code.ck
new file mode 100644
index 0000000..b5b23c7
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-over-code.ck
@@ -0,0 +1,11 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(mmap-over-code) begin
7(mmap-over-code) open "sample.txt"
8(mmap-over-code) try to mmap over code segment
9(mmap-over-code) end
10EOF
11pass;
diff --git a/pintos-progos/tests/vm/mmap-over-data.c b/pintos-progos/tests/vm/mmap-over-data.c
new file mode 100644
index 0000000..9ea5d49
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-over-data.c
@@ -0,0 +1,21 @@
1/* Verifies that mapping over the data segment is disallowed. */
2
3#include <stdint.h>
4#include <round.h>
5#include <syscall.h>
6#include "tests/lib.h"
7#include "tests/main.h"
8
9static char x;
10
11void
12test_main (void)
13{
14 uintptr_t x_page = ROUND_DOWN ((uintptr_t) &x, 4096);
15 int handle;
16
17 CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
18 CHECK (mmap (handle, (void *) x_page) == MAP_FAILED,
19 "try to mmap over data segment");
20}
21
diff --git a/pintos-progos/tests/vm/mmap-over-data.ck b/pintos-progos/tests/vm/mmap-over-data.ck
new file mode 100644
index 0000000..98770cc
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-over-data.ck
@@ -0,0 +1,11 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(mmap-over-data) begin
7(mmap-over-data) open "sample.txt"
8(mmap-over-data) try to mmap over data segment
9(mmap-over-data) end
10EOF
11pass;
diff --git a/pintos-progos/tests/vm/mmap-over-stk.c b/pintos-progos/tests/vm/mmap-over-stk.c
new file mode 100644
index 0000000..4e241e8
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-over-stk.c
@@ -0,0 +1,19 @@
1/* Verifies that mapping over the stack segment is disallowed. */
2
3#include <stdint.h>
4#include <round.h>
5#include <syscall.h>
6#include "tests/lib.h"
7#include "tests/main.h"
8
9void
10test_main (void)
11{
12 int handle;
13 uintptr_t handle_page = ROUND_DOWN ((uintptr_t) &handle, 4096);
14
15 CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
16 CHECK (mmap (handle, (void *) handle_page) == MAP_FAILED,
17 "try to mmap over stack segment");
18}
19
diff --git a/pintos-progos/tests/vm/mmap-over-stk.ck b/pintos-progos/tests/vm/mmap-over-stk.ck
new file mode 100644
index 0000000..e6880cf
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-over-stk.ck
@@ -0,0 +1,11 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(mmap-over-stk) begin
7(mmap-over-stk) open "sample.txt"
8(mmap-over-stk) try to mmap over stack segment
9(mmap-over-stk) end
10EOF
11pass;
diff --git a/pintos-progos/tests/vm/mmap-overlap.c b/pintos-progos/tests/vm/mmap-overlap.c
new file mode 100644
index 0000000..668ae5f
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-overlap.c
@@ -0,0 +1,20 @@
1/* Verifies that overlapping memory mappings are disallowed. */
2
3#include <syscall.h>
4#include "tests/vm/sample.inc"
5#include "tests/lib.h"
6#include "tests/main.h"
7
8void
9test_main (void)
10{
11 char *start = (char *) 0x10000000;
12 int fd[2];
13
14 CHECK ((fd[0] = open ("zeros")) > 1, "open \"zeros\" once");
15 CHECK (mmap (fd[0], start) != MAP_FAILED, "mmap \"zeros\"");
16 CHECK ((fd[1] = open ("zeros")) > 1 && fd[0] != fd[1],
17 "open \"zeros\" again");
18 CHECK (mmap (fd[1], start + 4096) == MAP_FAILED,
19 "try to mmap \"zeros\" again");
20}
diff --git a/pintos-progos/tests/vm/mmap-overlap.ck b/pintos-progos/tests/vm/mmap-overlap.ck
new file mode 100644
index 0000000..f13801e
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-overlap.ck
@@ -0,0 +1,13 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(mmap-overlap) begin
7(mmap-overlap) open "zeros" once
8(mmap-overlap) mmap "zeros"
9(mmap-overlap) open "zeros" again
10(mmap-overlap) try to mmap "zeros" again
11(mmap-overlap) end
12EOF
13pass;
diff --git a/pintos-progos/tests/vm/mmap-read.c b/pintos-progos/tests/vm/mmap-read.c
new file mode 100644
index 0000000..c0f23a1
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-read.c
@@ -0,0 +1,32 @@
1/* Uses a memory mapping to read a file. */
2
3#include <string.h>
4#include <syscall.h>
5#include "tests/vm/sample.inc"
6#include "tests/lib.h"
7#include "tests/main.h"
8
9void
10test_main (void)
11{
12 char *actual = (char *) 0x10000000;
13 int handle;
14 mapid_t map;
15 size_t i;
16
17 CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
18 CHECK ((map = mmap (handle, actual)) != MAP_FAILED, "mmap \"sample.txt\"");
19
20 /* Check that data is correct. */
21 if (memcmp (actual, sample, strlen (sample)))
22 fail ("read of mmap'd file reported bad data");
23
24 /* Verify that data is followed by zeros. */
25 for (i = strlen (sample); i < 4096; i++)
26 if (actual[i] != 0)
27 fail ("byte %zu of mmap'd region has value %02hhx (should be 0)",
28 i, actual[i]);
29
30 munmap (map);
31 close (handle);
32}
diff --git a/pintos-progos/tests/vm/mmap-read.ck b/pintos-progos/tests/vm/mmap-read.ck
new file mode 100644
index 0000000..95ab790
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-read.ck
@@ -0,0 +1,11 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(mmap-read) begin
7(mmap-read) open "sample.txt"
8(mmap-read) mmap "sample.txt"
9(mmap-read) end
10EOF
11pass;
diff --git a/pintos-progos/tests/vm/mmap-remove.c b/pintos-progos/tests/vm/mmap-remove.c
new file mode 100644
index 0000000..5f7444d
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-remove.c
@@ -0,0 +1,43 @@
1/* Deletes and closes file that is mapped into memory
2 and verifies that it can still be read through the mapping. */
3
4#include <string.h>
5#include <syscall.h>
6#include "tests/vm/sample.inc"
7#include "tests/lib.h"
8#include "tests/main.h"
9
10void
11test_main (void)
12{
13 char *actual = (char *) 0x10000000;
14 int handle;
15 mapid_t map;
16 size_t i;
17
18 /* Map file. */
19 CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
20 CHECK ((map = mmap (handle, actual)) != MAP_FAILED, "mmap \"sample.txt\"");
21
22 /* Close file and delete it. */
23 close (handle);
24 CHECK (remove ("sample.txt"), "remove \"sample.txt\"");
25 CHECK (open ("sample.txt") == -1, "try to open \"sample.txt\"");
26
27 /* Create a new file in hopes of overwriting data from the old
28 one, in case the file system has incorrectly freed the
29 file's data. */
30 CHECK (create ("another", 4096 * 10), "create \"another\"");
31
32 /* Check that mapped data is correct. */
33 if (memcmp (actual, sample, strlen (sample)))
34 fail ("read of mmap'd file reported bad data");
35
36 /* Verify that data is followed by zeros. */
37 for (i = strlen (sample); i < 4096; i++)
38 if (actual[i] != 0)
39 fail ("byte %zu of mmap'd region has value %02hhx (should be 0)",
40 i, actual[i]);
41
42 munmap (map);
43}
diff --git a/pintos-progos/tests/vm/mmap-remove.ck b/pintos-progos/tests/vm/mmap-remove.ck
new file mode 100644
index 0000000..d3cc938
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-remove.ck
@@ -0,0 +1,14 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(mmap-remove) begin
7(mmap-remove) open "sample.txt"
8(mmap-remove) mmap "sample.txt"
9(mmap-remove) remove "sample.txt"
10(mmap-remove) try to open "sample.txt"
11(mmap-remove) create "another"
12(mmap-remove) end
13EOF
14pass;
diff --git a/pintos-progos/tests/vm/mmap-shuffle.c b/pintos-progos/tests/vm/mmap-shuffle.c
new file mode 100644
index 0000000..29921ad
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-shuffle.c
@@ -0,0 +1,38 @@
1/* Creates a 128 kB file and repeatedly shuffles data in it
2 through a memory mapping. */
3
4#include <stdio.h>
5#include <string.h>
6#include <syscall.h>
7#include "tests/arc4.h"
8#include "tests/cksum.h"
9#include "tests/lib.h"
10#include "tests/main.h"
11
12#define SIZE (128 * 1024)
13
14static char *buf = (char *) 0x10000000;
15
16void
17test_main (void)
18{
19 size_t i;
20 int handle;
21
22 /* Create file, mmap. */
23 CHECK (create ("buffer", SIZE), "create \"buffer\"");
24 CHECK ((handle = open ("buffer")) > 1, "open \"buffer\"");
25 CHECK (mmap (handle, buf) != MAP_FAILED, "mmap \"buffer\"");
26
27 /* Initialize. */
28 for (i = 0; i < SIZE; i++)
29 buf[i] = i * 257;
30 msg ("init: cksum=%lu", cksum (buf, SIZE));
31
32 /* Shuffle repeatedly. */
33 for (i = 0; i < 10; i++)
34 {
35 shuffle (buf, SIZE, 1);
36 msg ("shuffle %zu: cksum=%lu", i, cksum (buf, SIZE));
37 }
38}
diff --git a/pintos-progos/tests/vm/mmap-shuffle.ck b/pintos-progos/tests/vm/mmap-shuffle.ck
new file mode 100644
index 0000000..c158301
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-shuffle.ck
@@ -0,0 +1,47 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5use tests::cksum;
6use tests::lib;
7
8my ($init, @shuffle);
9if (1) {
10 # Use precalculated values.
11 $init = 3115322833;
12 @shuffle = (1691062564, 1973575879, 1647619479, 96566261, 3885786467,
13 3022003332, 3614934266, 2704001777, 735775156, 1864109763);
14} else {
15 # Recalculate values.
16 my ($buf) = "";
17 for my $i (0...128 * 1024 - 1) {
18 $buf .= chr (($i * 257) & 0xff);
19 }
20 $init = cksum ($buf);
21
22 random_init (0);
23 for my $i (1...10) {
24 $buf = shuffle ($buf, length ($buf), 1);
25 push (@shuffle, cksum ($buf));
26 }
27}
28
29check_expected (IGNORE_EXIT_CODES => 1, [<<EOF]);
30(mmap-shuffle) begin
31(mmap-shuffle) create "buffer"
32(mmap-shuffle) open "buffer"
33(mmap-shuffle) mmap "buffer"
34(mmap-shuffle) init: cksum=$init
35(mmap-shuffle) shuffle 0: cksum=$shuffle[0]
36(mmap-shuffle) shuffle 1: cksum=$shuffle[1]
37(mmap-shuffle) shuffle 2: cksum=$shuffle[2]
38(mmap-shuffle) shuffle 3: cksum=$shuffle[3]
39(mmap-shuffle) shuffle 4: cksum=$shuffle[4]
40(mmap-shuffle) shuffle 5: cksum=$shuffle[5]
41(mmap-shuffle) shuffle 6: cksum=$shuffle[6]
42(mmap-shuffle) shuffle 7: cksum=$shuffle[7]
43(mmap-shuffle) shuffle 8: cksum=$shuffle[8]
44(mmap-shuffle) shuffle 9: cksum=$shuffle[9]
45(mmap-shuffle) end
46EOF
47pass;
diff --git a/pintos-progos/tests/vm/mmap-twice.c b/pintos-progos/tests/vm/mmap-twice.c
new file mode 100644
index 0000000..d277a37
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-twice.c
@@ -0,0 +1,28 @@
1/* Maps the same file into memory twice and verifies that the
2 same data is readable in both. */
3
4#include <string.h>
5#include <syscall.h>
6#include "tests/vm/sample.inc"
7#include "tests/lib.h"
8#include "tests/main.h"
9
10void
11test_main (void)
12{
13 char *actual[2] = {(char *) 0x10000000, (char *) 0x20000000};
14 size_t i;
15 int handle[2];
16
17 for (i = 0; i < 2; i++)
18 {
19 CHECK ((handle[i] = open ("sample.txt")) > 1,
20 "open \"sample.txt\" #%zu", i);
21 CHECK (mmap (handle[i], actual[i]) != MAP_FAILED,
22 "mmap \"sample.txt\" #%zu at %p", i, (void *) actual[i]);
23 }
24
25 for (i = 0; i < 2; i++)
26 CHECK (!memcmp (actual[i], sample, strlen (sample)),
27 "compare mmap'd file %zu against data", i);
28}
diff --git a/pintos-progos/tests/vm/mmap-twice.ck b/pintos-progos/tests/vm/mmap-twice.ck
new file mode 100644
index 0000000..05e9724
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-twice.ck
@@ -0,0 +1,15 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(mmap-twice) begin
7(mmap-twice) open "sample.txt" #0
8(mmap-twice) mmap "sample.txt" #0 at 0x10000000
9(mmap-twice) open "sample.txt" #1
10(mmap-twice) mmap "sample.txt" #1 at 0x20000000
11(mmap-twice) compare mmap'd file 0 against data
12(mmap-twice) compare mmap'd file 1 against data
13(mmap-twice) end
14EOF
15pass;
diff --git a/pintos-progos/tests/vm/mmap-unmap.c b/pintos-progos/tests/vm/mmap-unmap.c
new file mode 100644
index 0000000..d35a79e
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-unmap.c
@@ -0,0 +1,23 @@
1/* Maps and unmaps a file and verifies that the mapped region is
2 inaccessible afterward. */
3
4#include <syscall.h>
5#include "tests/vm/sample.inc"
6#include "tests/lib.h"
7#include "tests/main.h"
8
9#define ACTUAL ((void *) 0x10000000)
10
11void
12test_main (void)
13{
14 int handle;
15 mapid_t map;
16
17 CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
18 CHECK ((map = mmap (handle, ACTUAL)) != MAP_FAILED, "mmap \"sample.txt\"");
19
20 munmap (map);
21
22 fail ("unmapped memory is readable (%d)", *(int *) ACTUAL);
23}
diff --git a/pintos-progos/tests/vm/mmap-unmap.ck b/pintos-progos/tests/vm/mmap-unmap.ck
new file mode 100644
index 0000000..119658c
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-unmap.ck
@@ -0,0 +1,7 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5use tests::vm::process_death;
6
7check_process_death ('mmap-unmap');
diff --git a/pintos-progos/tests/vm/mmap-write.c b/pintos-progos/tests/vm/mmap-write.c
new file mode 100644
index 0000000..46e8043
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-write.c
@@ -0,0 +1,32 @@
1/* Writes to a file through a mapping, and unmaps the file,
2 then reads the data in the file back using the read system
3 call to verify. */
4
5#include <string.h>
6#include <syscall.h>
7#include "tests/vm/sample.inc"
8#include "tests/lib.h"
9#include "tests/main.h"
10
11#define ACTUAL ((void *) 0x10000000)
12
13void
14test_main (void)
15{
16 int handle;
17 mapid_t map;
18 char buf[1024];
19
20 /* Write file via mmap. */
21 CHECK (create ("sample.txt", strlen (sample)), "create \"sample.txt\"");
22 CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
23 CHECK ((map = mmap (handle, ACTUAL)) != MAP_FAILED, "mmap \"sample.txt\"");
24 memcpy (ACTUAL, sample, strlen (sample));
25 munmap (map);
26
27 /* Read back via read(). */
28 read (handle, buf, strlen (sample));
29 CHECK (!memcmp (buf, sample, strlen (sample)),
30 "compare read data against written data");
31 close (handle);
32}
diff --git a/pintos-progos/tests/vm/mmap-write.ck b/pintos-progos/tests/vm/mmap-write.ck
new file mode 100644
index 0000000..d2c9cc5
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-write.ck
@@ -0,0 +1,13 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(mmap-write) begin
7(mmap-write) create "sample.txt"
8(mmap-write) open "sample.txt"
9(mmap-write) mmap "sample.txt"
10(mmap-write) compare read data against written data
11(mmap-write) end
12EOF
13pass;
diff --git a/pintos-progos/tests/vm/mmap-zero.c b/pintos-progos/tests/vm/mmap-zero.c
new file mode 100644
index 0000000..368b759
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-zero.c
@@ -0,0 +1,27 @@
1/* Tries to map a zero-length file, which may or may not work but
2 should not terminate the process or crash.
3 Then dereferences the address that we tried to map,
4 and the process must be terminated with -1 exit code. */
5
6#include <syscall.h>
7#include "tests/lib.h"
8#include "tests/main.h"
9
10void
11test_main (void)
12{
13 char *data = (char *) 0x7f000000;
14 int handle;
15
16 CHECK (create ("empty", 0), "create empty file \"empty\"");
17 CHECK ((handle = open ("empty")) > 1, "open \"empty\"");
18
19 /* Calling mmap() might succeed or fail. We don't care. */
20 msg ("mmap \"empty\"");
21 mmap (handle, data);
22
23 /* Regardless of whether the call worked, *data should cause
24 the process to be terminated. */
25 fail ("unmapped memory is readable (%d)", *data);
26}
27
diff --git a/pintos-progos/tests/vm/mmap-zero.ck b/pintos-progos/tests/vm/mmap-zero.ck
new file mode 100644
index 0000000..6033d5d
--- /dev/null
+++ b/pintos-progos/tests/vm/mmap-zero.ck
@@ -0,0 +1,12 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']);
6(mmap-zero) begin
7(mmap-zero) create empty file "empty"
8(mmap-zero) open "empty"
9(mmap-zero) mmap "empty"
10mmap-zero: exit(-1)
11EOF
12pass;
diff --git a/pintos-progos/tests/vm/page-linear.c b/pintos-progos/tests/vm/page-linear.c
new file mode 100644
index 0000000..652a47b
--- /dev/null
+++ b/pintos-progos/tests/vm/page-linear.c
@@ -0,0 +1,44 @@
1/* Encrypts, then decrypts, 2 MB of memory and verifies that the
2 values are as they should be. */
3
4#include <string.h>
5#include "tests/arc4.h"
6#include "tests/lib.h"
7#include "tests/main.h"
8
9#define SIZE (2 * 1024 * 1024)
10
11static char buf[SIZE];
12
13void
14test_main (void)
15{
16 struct arc4 arc4;
17 size_t i;
18
19 /* Initialize to 0x5a. */
20 msg ("initialize");
21 memset (buf, 0x5a, sizeof buf);
22
23 /* Check that it's all 0x5a. */
24 msg ("read pass");
25 for (i = 0; i < SIZE; i++)
26 if (buf[i] != 0x5a)
27 fail ("byte %zu != 0x5a", i);
28
29 /* Encrypt zeros. */
30 msg ("read/modify/write pass one");
31 arc4_init (&arc4, "foobar", 6);
32 arc4_crypt (&arc4, buf, SIZE);
33
34 /* Decrypt back to zeros. */
35 msg ("read/modify/write pass two");
36 arc4_init (&arc4, "foobar", 6);
37 arc4_crypt (&arc4, buf, SIZE);
38
39 /* Check that it's all 0x5a. */
40 msg ("read pass");
41 for (i = 0; i < SIZE; i++)
42 if (buf[i] != 0x5a)
43 fail ("byte %zu != 0x5a", i);
44}
diff --git a/pintos-progos/tests/vm/page-linear.ck b/pintos-progos/tests/vm/page-linear.ck
new file mode 100644
index 0000000..dcbc884
--- /dev/null
+++ b/pintos-progos/tests/vm/page-linear.ck
@@ -0,0 +1,14 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(page-linear) begin
7(page-linear) initialize
8(page-linear) read pass
9(page-linear) read/modify/write pass one
10(page-linear) read/modify/write pass two
11(page-linear) read pass
12(page-linear) end
13EOF
14pass;
diff --git a/pintos-progos/tests/vm/page-merge-mm.c b/pintos-progos/tests/vm/page-merge-mm.c
new file mode 100644
index 0000000..908c71c
--- /dev/null
+++ b/pintos-progos/tests/vm/page-merge-mm.c
@@ -0,0 +1,8 @@
1#include "tests/main.h"
2#include "tests/vm/parallel-merge.h"
3
4void
5test_main (void)
6{
7 parallel_merge ("child-qsort-mm", 80);
8}
diff --git a/pintos-progos/tests/vm/page-merge-mm.ck b/pintos-progos/tests/vm/page-merge-mm.ck
new file mode 100644
index 0000000..74fa980
--- /dev/null
+++ b/pintos-progos/tests/vm/page-merge-mm.ck
@@ -0,0 +1,29 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(page-merge-mm) begin
7(page-merge-mm) init
8(page-merge-mm) sort chunk 0
9(page-merge-mm) sort chunk 1
10(page-merge-mm) sort chunk 2
11(page-merge-mm) sort chunk 3
12(page-merge-mm) sort chunk 4
13(page-merge-mm) sort chunk 5
14(page-merge-mm) sort chunk 6
15(page-merge-mm) sort chunk 7
16(page-merge-mm) wait for child 0
17(page-merge-mm) wait for child 1
18(page-merge-mm) wait for child 2
19(page-merge-mm) wait for child 3
20(page-merge-mm) wait for child 4
21(page-merge-mm) wait for child 5
22(page-merge-mm) wait for child 6
23(page-merge-mm) wait for child 7
24(page-merge-mm) merge
25(page-merge-mm) verify
26(page-merge-mm) success, buf_idx=1,048,576
27(page-merge-mm) end
28EOF
29pass;
diff --git a/pintos-progos/tests/vm/page-merge-par.c b/pintos-progos/tests/vm/page-merge-par.c
new file mode 100644
index 0000000..e7e1609
--- /dev/null
+++ b/pintos-progos/tests/vm/page-merge-par.c
@@ -0,0 +1,8 @@
1#include "tests/main.h"
2#include "tests/vm/parallel-merge.h"
3
4void
5test_main (void)
6{
7 parallel_merge ("child-sort", 123);
8}
diff --git a/pintos-progos/tests/vm/page-merge-par.ck b/pintos-progos/tests/vm/page-merge-par.ck
new file mode 100644
index 0000000..31f8aa7
--- /dev/null
+++ b/pintos-progos/tests/vm/page-merge-par.ck
@@ -0,0 +1,29 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(page-merge-par) begin
7(page-merge-par) init
8(page-merge-par) sort chunk 0
9(page-merge-par) sort chunk 1
10(page-merge-par) sort chunk 2
11(page-merge-par) sort chunk 3
12(page-merge-par) sort chunk 4
13(page-merge-par) sort chunk 5
14(page-merge-par) sort chunk 6
15(page-merge-par) sort chunk 7
16(page-merge-par) wait for child 0
17(page-merge-par) wait for child 1
18(page-merge-par) wait for child 2
19(page-merge-par) wait for child 3
20(page-merge-par) wait for child 4
21(page-merge-par) wait for child 5
22(page-merge-par) wait for child 6
23(page-merge-par) wait for child 7
24(page-merge-par) merge
25(page-merge-par) verify
26(page-merge-par) success, buf_idx=1,048,576
27(page-merge-par) end
28EOF
29pass;
diff --git a/pintos-progos/tests/vm/page-merge-seq.c b/pintos-progos/tests/vm/page-merge-seq.c
new file mode 100644
index 0000000..12e3880
--- /dev/null
+++ b/pintos-progos/tests/vm/page-merge-seq.c
@@ -0,0 +1,137 @@
1/* Generates about 1 MB of random data that is then divided into
2 16 chunks. A separate subprocess sorts each chunk in
3 sequence. Then we merge the chunks and verify that the result
4 is what it should be. */
5
6#include <syscall.h>
7#include "tests/arc4.h"
8#include "tests/lib.h"
9#include "tests/main.h"
10
11/* This is the max file size for an older version of the Pintos
12 file system that had 126 direct blocks each pointing to a
13 single disk sector. We could raise it now. */
14#define CHUNK_SIZE (126 * 512)
15#define CHUNK_CNT 16 /* Number of chunks. */
16#define DATA_SIZE (CHUNK_CNT * CHUNK_SIZE) /* Buffer size. */
17
18unsigned char buf1[DATA_SIZE], buf2[DATA_SIZE];
19size_t histogram[256];
20
21/* Initialize buf1 with random data,
22 then count the number of instances of each value within it. */
23static void
24init (void)
25{
26 struct arc4 arc4;
27 size_t i;
28
29 msg ("init");
30
31 arc4_init (&arc4, "foobar", 6);
32 arc4_crypt (&arc4, buf1, sizeof buf1);
33 for (i = 0; i < sizeof buf1; i++)
34 histogram[buf1[i]]++;
35}
36
37/* Sort each chunk of buf1 using a subprocess. */
38static void
39sort_chunks (void)
40{
41 size_t i;
42
43 create ("buffer", CHUNK_SIZE);
44 for (i = 0; i < CHUNK_CNT; i++)
45 {
46 pid_t child;
47 int handle;
48
49 msg ("sort chunk %zu", i);
50
51 /* Write this chunk to a file. */
52 quiet = true;
53 CHECK ((handle = open ("buffer")) > 1, "open \"buffer\"");
54 write (handle, buf1 + CHUNK_SIZE * i, CHUNK_SIZE);
55 close (handle);
56
57 /* Sort with subprocess. */
58 CHECK ((child = exec ("child-sort buffer")) != -1,
59 "exec \"child-sort buffer\"");
60 CHECK (wait (child) == 123, "wait for child-sort");
61
62 /* Read chunk back from file. */
63 CHECK ((handle = open ("buffer")) > 1, "open \"buffer\"");
64 read (handle, buf1 + CHUNK_SIZE * i, CHUNK_SIZE);
65 close (handle);
66
67 quiet = false;
68 }
69}
70
71/* Merge the sorted chunks in buf1 into a fully sorted buf2. */
72static void
73merge (void)
74{
75 unsigned char *mp[CHUNK_CNT];
76 size_t mp_left;
77 unsigned char *op;
78 size_t i;
79
80 msg ("merge");
81
82 /* Initialize merge pointers. */
83 mp_left = CHUNK_CNT;
84 for (i = 0; i < CHUNK_CNT; i++)
85 mp[i] = buf1 + CHUNK_SIZE * i;
86
87 /* Merge. */
88 op = buf2;
89 while (mp_left > 0)
90 {
91 /* Find smallest value. */
92 size_t min = 0;
93 for (i = 1; i < mp_left; i++)
94 if (*mp[i] < *mp[min])
95 min = i;
96
97 /* Append value to buf2. */
98 *op++ = *mp[min];
99
100 /* Advance merge pointer.
101 Delete this chunk from the set if it's emptied. */
102 if ((++mp[min] - buf1) % CHUNK_SIZE == 0)
103 mp[min] = mp[--mp_left];
104 }
105}
106
107static void
108verify (void)
109{
110 size_t buf_idx;
111 size_t hist_idx;
112
113 msg ("verify");
114
115 buf_idx = 0;
116 for (hist_idx = 0; hist_idx < sizeof histogram / sizeof *histogram;
117 hist_idx++)
118 {
119 while (histogram[hist_idx]-- > 0)
120 {
121 if (buf2[buf_idx] != hist_idx)
122 fail ("bad value %d in byte %zu", buf2[buf_idx], buf_idx);
123 buf_idx++;
124 }
125 }
126
127 msg ("success, buf_idx=%'zu", buf_idx);
128}
129
130void
131test_main (void)
132{
133 init ();
134 sort_chunks ();
135 merge ();
136 verify ();
137}
diff --git a/pintos-progos/tests/vm/page-merge-seq.ck b/pintos-progos/tests/vm/page-merge-seq.ck
new file mode 100644
index 0000000..d78f69d
--- /dev/null
+++ b/pintos-progos/tests/vm/page-merge-seq.ck
@@ -0,0 +1,29 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(page-merge-seq) begin
7(page-merge-seq) init
8(page-merge-seq) sort chunk 0
9(page-merge-seq) sort chunk 1
10(page-merge-seq) sort chunk 2
11(page-merge-seq) sort chunk 3
12(page-merge-seq) sort chunk 4
13(page-merge-seq) sort chunk 5
14(page-merge-seq) sort chunk 6
15(page-merge-seq) sort chunk 7
16(page-merge-seq) sort chunk 8
17(page-merge-seq) sort chunk 9
18(page-merge-seq) sort chunk 10
19(page-merge-seq) sort chunk 11
20(page-merge-seq) sort chunk 12
21(page-merge-seq) sort chunk 13
22(page-merge-seq) sort chunk 14
23(page-merge-seq) sort chunk 15
24(page-merge-seq) merge
25(page-merge-seq) verify
26(page-merge-seq) success, buf_idx=1,032,192
27(page-merge-seq) end
28EOF
29pass;
diff --git a/pintos-progos/tests/vm/page-merge-stk.c b/pintos-progos/tests/vm/page-merge-stk.c
new file mode 100644
index 0000000..5eb1069
--- /dev/null
+++ b/pintos-progos/tests/vm/page-merge-stk.c
@@ -0,0 +1,8 @@
1#include "tests/main.h"
2#include "tests/vm/parallel-merge.h"
3
4void
5test_main (void)
6{
7 parallel_merge ("child-qsort", 72);
8}
diff --git a/pintos-progos/tests/vm/page-merge-stk.ck b/pintos-progos/tests/vm/page-merge-stk.ck
new file mode 100644
index 0000000..c5bc1ae
--- /dev/null
+++ b/pintos-progos/tests/vm/page-merge-stk.ck
@@ -0,0 +1,29 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(page-merge-stk) begin
7(page-merge-stk) init
8(page-merge-stk) sort chunk 0
9(page-merge-stk) sort chunk 1
10(page-merge-stk) sort chunk 2
11(page-merge-stk) sort chunk 3
12(page-merge-stk) sort chunk 4
13(page-merge-stk) sort chunk 5
14(page-merge-stk) sort chunk 6
15(page-merge-stk) sort chunk 7
16(page-merge-stk) wait for child 0
17(page-merge-stk) wait for child 1
18(page-merge-stk) wait for child 2
19(page-merge-stk) wait for child 3
20(page-merge-stk) wait for child 4
21(page-merge-stk) wait for child 5
22(page-merge-stk) wait for child 6
23(page-merge-stk) wait for child 7
24(page-merge-stk) merge
25(page-merge-stk) verify
26(page-merge-stk) success, buf_idx=1,048,576
27(page-merge-stk) end
28EOF
29pass;
diff --git a/pintos-progos/tests/vm/page-parallel.c b/pintos-progos/tests/vm/page-parallel.c
new file mode 100644
index 0000000..9d619e0
--- /dev/null
+++ b/pintos-progos/tests/vm/page-parallel.c
@@ -0,0 +1,21 @@
1/* Runs 4 child-linear processes at once. */
2
3#include <syscall.h>
4#include "tests/lib.h"
5#include "tests/main.h"
6
7#define CHILD_CNT 4
8
9void
10test_main (void)
11{
12 pid_t children[CHILD_CNT];
13 int i;
14
15 for (i = 0; i < CHILD_CNT; i++)
16 CHECK ((children[i] = exec ("child-linear")) != -1,
17 "exec \"child-linear\"");
18
19 for (i = 0; i < CHILD_CNT; i++)
20 CHECK (wait (children[i]) == 0x42, "wait for child %d", i);
21}
diff --git a/pintos-progos/tests/vm/page-parallel.ck b/pintos-progos/tests/vm/page-parallel.ck
new file mode 100644
index 0000000..90c14ef
--- /dev/null
+++ b/pintos-progos/tests/vm/page-parallel.ck
@@ -0,0 +1,17 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(page-parallel) begin
7(page-parallel) exec "child-linear"
8(page-parallel) exec "child-linear"
9(page-parallel) exec "child-linear"
10(page-parallel) exec "child-linear"
11(page-parallel) wait for child 0
12(page-parallel) wait for child 1
13(page-parallel) wait for child 2
14(page-parallel) wait for child 3
15(page-parallel) end
16EOF
17pass;
diff --git a/pintos-progos/tests/vm/page-shuffle.c b/pintos-progos/tests/vm/page-shuffle.c
new file mode 100644
index 0000000..095a9da
--- /dev/null
+++ b/pintos-progos/tests/vm/page-shuffle.c
@@ -0,0 +1,30 @@
1/* Shuffles a 128 kB data buffer 10 times, printing the checksum
2 after each time. */
3
4#include <stdbool.h>
5#include "tests/arc4.h"
6#include "tests/cksum.h"
7#include "tests/lib.h"
8#include "tests/main.h"
9
10#define SIZE (128 * 1024)
11
12static char buf[SIZE];
13
14void
15test_main (void)
16{
17 size_t i;
18
19 /* Initialize. */
20 for (i = 0; i < sizeof buf; i++)
21 buf[i] = i * 257;
22 msg ("init: cksum=%lu", cksum (buf, sizeof buf));
23
24 /* Shuffle repeatedly. */
25 for (i = 0; i < 10; i++)
26 {
27 shuffle (buf, sizeof buf, 1);
28 msg ("shuffle %zu: cksum=%lu", i, cksum (buf, sizeof buf));
29 }
30}
diff --git a/pintos-progos/tests/vm/page-shuffle.ck b/pintos-progos/tests/vm/page-shuffle.ck
new file mode 100644
index 0000000..6447d38
--- /dev/null
+++ b/pintos-progos/tests/vm/page-shuffle.ck
@@ -0,0 +1,44 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5use tests::cksum;
6use tests::lib;
7
8my ($init, @shuffle);
9if (1) {
10 # Use precalculated values.
11 $init = 3115322833;
12 @shuffle = (1691062564, 1973575879, 1647619479, 96566261, 3885786467,
13 3022003332, 3614934266, 2704001777, 735775156, 1864109763);
14} else {
15 # Recalculate values.
16 my ($buf) = "";
17 for my $i (0...128 * 1024 - 1) {
18 $buf .= chr (($i * 257) & 0xff);
19 }
20 $init = cksum ($buf);
21
22 random_init (0);
23 for my $i (1...10) {
24 $buf = shuffle ($buf, length ($buf), 1);
25 push (@shuffle, cksum ($buf));
26 }
27}
28
29check_expected (IGNORE_EXIT_CODES => 1, [<<EOF]);
30(page-shuffle) begin
31(page-shuffle) init: cksum=$init
32(page-shuffle) shuffle 0: cksum=$shuffle[0]
33(page-shuffle) shuffle 1: cksum=$shuffle[1]
34(page-shuffle) shuffle 2: cksum=$shuffle[2]
35(page-shuffle) shuffle 3: cksum=$shuffle[3]
36(page-shuffle) shuffle 4: cksum=$shuffle[4]
37(page-shuffle) shuffle 5: cksum=$shuffle[5]
38(page-shuffle) shuffle 6: cksum=$shuffle[6]
39(page-shuffle) shuffle 7: cksum=$shuffle[7]
40(page-shuffle) shuffle 8: cksum=$shuffle[8]
41(page-shuffle) shuffle 9: cksum=$shuffle[9]
42(page-shuffle) end
43EOF
44pass;
diff --git a/pintos-progos/tests/vm/parallel-merge.c b/pintos-progos/tests/vm/parallel-merge.c
new file mode 100644
index 0000000..cc09bb1
--- /dev/null
+++ b/pintos-progos/tests/vm/parallel-merge.c
@@ -0,0 +1,149 @@
1/* Generates about 1 MB of random data that is then divided into
2 16 chunks. A separate subprocess sorts each chunk; the
3 subprocesses run in parallel. Then we merge the chunks and
4 verify that the result is what it should be. */
5
6#include "tests/vm/parallel-merge.h"
7#include <stdio.h>
8#include <syscall.h>
9#include "tests/arc4.h"
10#include "tests/lib.h"
11#include "tests/main.h"
12
13#define CHUNK_SIZE (128 * 1024)
14#define CHUNK_CNT 8 /* Number of chunks. */
15#define DATA_SIZE (CHUNK_CNT * CHUNK_SIZE) /* Buffer size. */
16
17unsigned char buf1[DATA_SIZE], buf2[DATA_SIZE];
18size_t histogram[256];
19
20/* Initialize buf1 with random data,
21 then count the number of instances of each value within it. */
22static void
23init (void)
24{
25 struct arc4 arc4;
26 size_t i;
27
28 msg ("init");
29
30 arc4_init (&arc4, "foobar", 6);
31 arc4_crypt (&arc4, buf1, sizeof buf1);
32 for (i = 0; i < sizeof buf1; i++)
33 histogram[buf1[i]]++;
34}
35
36/* Sort each chunk of buf1 using SUBPROCESS,
37 which is expected to return EXIT_STATUS. */
38static void
39sort_chunks (const char *subprocess, int exit_status)
40{
41 pid_t children[CHUNK_CNT];
42 size_t i;
43
44 for (i = 0; i < CHUNK_CNT; i++)
45 {
46 char fn[128];
47 char cmd[128];
48 int handle;
49
50 msg ("sort chunk %zu", i);
51
52 /* Write this chunk to a file. */
53 snprintf (fn, sizeof fn, "buf%zu", i);
54 create (fn, CHUNK_SIZE);
55 quiet = true;
56 CHECK ((handle = open (fn)) > 1, "open \"%s\"", fn);
57 write (handle, buf1 + CHUNK_SIZE * i, CHUNK_SIZE);
58 close (handle);
59
60 /* Sort with subprocess. */
61 snprintf (cmd, sizeof cmd, "%s %s", subprocess, fn);
62 CHECK ((children[i] = exec (cmd)) != -1, "exec \"%s\"", cmd);
63 quiet = false;
64 }
65
66 for (i = 0; i < CHUNK_CNT; i++)
67 {
68 char fn[128];
69 int handle;
70
71 CHECK (wait (children[i]) == exit_status, "wait for child %zu", i);
72
73 /* Read chunk back from file. */
74 quiet = true;
75 snprintf (fn, sizeof fn, "buf%zu", i);
76 CHECK ((handle = open (fn)) > 1, "open \"%s\"", fn);
77 read (handle, buf1 + CHUNK_SIZE * i, CHUNK_SIZE);
78 close (handle);
79 quiet = false;
80 }
81}
82
83/* Merge the sorted chunks in buf1 into a fully sorted buf2. */
84static void
85merge (void)
86{
87 unsigned char *mp[CHUNK_CNT];
88 size_t mp_left;
89 unsigned char *op;
90 size_t i;
91
92 msg ("merge");
93
94 /* Initialize merge pointers. */
95 mp_left = CHUNK_CNT;
96 for (i = 0; i < CHUNK_CNT; i++)
97 mp[i] = buf1 + CHUNK_SIZE * i;
98
99 /* Merge. */
100 op = buf2;
101 while (mp_left > 0)
102 {
103 /* Find smallest value. */
104 size_t min = 0;
105 for (i = 1; i < mp_left; i++)
106 if (*mp[i] < *mp[min])
107 min = i;
108
109 /* Append value to buf2. */
110 *op++ = *mp[min];
111
112 /* Advance merge pointer.
113 Delete this chunk from the set if it's emptied. */
114 if ((++mp[min] - buf1) % CHUNK_SIZE == 0)
115 mp[min] = mp[--mp_left];
116 }
117}
118
119static void
120verify (void)
121{
122 size_t buf_idx;
123 size_t hist_idx;
124
125 msg ("verify");
126
127 buf_idx = 0;
128 for (hist_idx = 0; hist_idx < sizeof histogram / sizeof *histogram;
129 hist_idx++)
130 {
131 while (histogram[hist_idx]-- > 0)
132 {
133 if (buf2[buf_idx] != hist_idx)
134 fail ("bad value %d in byte %zu", buf2[buf_idx], buf_idx);
135 buf_idx++;
136 }
137 }
138
139 msg ("success, buf_idx=%'zu", buf_idx);
140}
141
142void
143parallel_merge (const char *child_name, int exit_status)
144{
145 init ();
146 sort_chunks (child_name, exit_status);
147 merge ();
148 verify ();
149}
diff --git a/pintos-progos/tests/vm/parallel-merge.h b/pintos-progos/tests/vm/parallel-merge.h
new file mode 100644
index 0000000..a6b6431
--- /dev/null
+++ b/pintos-progos/tests/vm/parallel-merge.h
@@ -0,0 +1,6 @@
1#ifndef TESTS_VM_PARALLEL_MERGE
2#define TESTS_VM_PARALLEL_MERGE 1
3
4void parallel_merge (const char *child_name, int exit_status);
5
6#endif /* tests/vm/parallel-merge.h */
diff --git a/pintos-progos/tests/vm/process_death.pm b/pintos-progos/tests/vm/process_death.pm
new file mode 100644
index 0000000..52039a1
--- /dev/null
+++ b/pintos-progos/tests/vm/process_death.pm
@@ -0,0 +1,22 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5
6sub check_process_death {
7 my ($proc_name) = @_;
8 our ($test);
9 my (@output) = read_text_file ("$test.output");
10
11 common_checks ("run", @output);
12 @output = get_core_output ("run", @output);
13 fail "First line of output is not `($proc_name) begin' message.\n"
14 if $output[0] ne "($proc_name) begin";
15 fail "Output missing '$proc_name: exit(-1)' message.\n"
16 if !grep ("$proc_name: exit(-1)" eq $_, @output);
17 fail "Output contains '($proc_name) end' message.\n"
18 if grep (/\($proc_name\) end/, @output);
19 pass;
20}
21
221;
diff --git a/pintos-progos/tests/vm/pt-bad-addr.c b/pintos-progos/tests/vm/pt-bad-addr.c
new file mode 100644
index 0000000..3ca4084
--- /dev/null
+++ b/pintos-progos/tests/vm/pt-bad-addr.c
@@ -0,0 +1,11 @@
1/* Accesses a bad address.
2 The process must be terminated with -1 exit code. */
3
4#include "tests/lib.h"
5#include "tests/main.h"
6
7void
8test_main (void)
9{
10 fail ("bad addr read as %d", *(int *) 0x04000000);
11}
diff --git a/pintos-progos/tests/vm/pt-bad-addr.ck b/pintos-progos/tests/vm/pt-bad-addr.ck
new file mode 100644
index 0000000..09ea039
--- /dev/null
+++ b/pintos-progos/tests/vm/pt-bad-addr.ck
@@ -0,0 +1,7 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5use tests::vm::process_death;
6
7check_process_death ('pt-bad-addr');
diff --git a/pintos-progos/tests/vm/pt-bad-read.c b/pintos-progos/tests/vm/pt-bad-read.c
new file mode 100644
index 0000000..ee791ff
--- /dev/null
+++ b/pintos-progos/tests/vm/pt-bad-read.c
@@ -0,0 +1,16 @@
1/* Reads from a file into a bad address.
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
13 CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
14 read (handle, (char *) &handle - 4096, 1);
15 fail ("survived reading data into bad address");
16}
diff --git a/pintos-progos/tests/vm/pt-bad-read.ck b/pintos-progos/tests/vm/pt-bad-read.ck
new file mode 100644
index 0000000..1f96bb4
--- /dev/null
+++ b/pintos-progos/tests/vm/pt-bad-read.ck
@@ -0,0 +1,10 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(pt-bad-read) begin
7(pt-bad-read) open "sample.txt"
8pt-bad-read: exit(-1)
9EOF
10pass;
diff --git a/pintos-progos/tests/vm/pt-big-stk-obj.c b/pintos-progos/tests/vm/pt-big-stk-obj.c
new file mode 100644
index 0000000..6b630ec
--- /dev/null
+++ b/pintos-progos/tests/vm/pt-big-stk-obj.c
@@ -0,0 +1,20 @@
1/* Allocates and writes to a 64 kB object on the stack.
2 This must succeed. */
3
4#include <string.h>
5#include "tests/arc4.h"
6#include "tests/cksum.h"
7#include "tests/lib.h"
8#include "tests/main.h"
9
10void
11test_main (void)
12{
13 char stk_obj[65536];
14 struct arc4 arc4;
15
16 arc4_init (&arc4, "foobar", 6);
17 memset (stk_obj, 0, sizeof stk_obj);
18 arc4_crypt (&arc4, stk_obj, sizeof stk_obj);
19 msg ("cksum: %lu", cksum (stk_obj, sizeof stk_obj));
20}
diff --git a/pintos-progos/tests/vm/pt-big-stk-obj.ck b/pintos-progos/tests/vm/pt-big-stk-obj.ck
new file mode 100644
index 0000000..eb5853a
--- /dev/null
+++ b/pintos-progos/tests/vm/pt-big-stk-obj.ck
@@ -0,0 +1,10 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(pt-big-stk-obj) begin
7(pt-big-stk-obj) cksum: 3256410166
8(pt-big-stk-obj) end
9EOF
10pass;
diff --git a/pintos-progos/tests/vm/pt-grow-bad.c b/pintos-progos/tests/vm/pt-grow-bad.c
new file mode 100644
index 0000000..d4beba2
--- /dev/null
+++ b/pintos-progos/tests/vm/pt-grow-bad.c
@@ -0,0 +1,14 @@
1/* Read from an address 4,096 bytes below the stack pointer.
2 The process must be terminated with -1 exit code. */
3
4#include <string.h>
5#include "tests/arc4.h"
6#include "tests/cksum.h"
7#include "tests/lib.h"
8#include "tests/main.h"
9
10void
11test_main (void)
12{
13 asm volatile ("movl -4096(%esp), %eax");
14}
diff --git a/pintos-progos/tests/vm/pt-grow-bad.ck b/pintos-progos/tests/vm/pt-grow-bad.ck
new file mode 100644
index 0000000..4c0ab8a
--- /dev/null
+++ b/pintos-progos/tests/vm/pt-grow-bad.ck
@@ -0,0 +1,9 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']);
6(pt-grow-bad) begin
7pt-grow-bad: exit(-1)
8EOF
9pass;
diff --git a/pintos-progos/tests/vm/pt-grow-pusha.c b/pintos-progos/tests/vm/pt-grow-pusha.c
new file mode 100644
index 0000000..f9762a5
--- /dev/null
+++ b/pintos-progos/tests/vm/pt-grow-pusha.c
@@ -0,0 +1,20 @@
1/* Expand the stack by 32 bytes all at once using the PUSHA
2 instruction.
3 This must succeed. */
4
5#include <string.h>
6#include "tests/arc4.h"
7#include "tests/cksum.h"
8#include "tests/lib.h"
9#include "tests/main.h"
10
11void
12test_main (void)
13{
14 asm volatile
15 ("movl %%esp, %%eax;" /* Save a copy of the stack pointer. */
16 "andl $0xfffff000, %%esp;" /* Move stack pointer to bottom of page. */
17 "pushal;" /* Push 32 bytes on stack at once. */
18 "movl %%eax, %%esp" /* Restore copied stack pointer. */
19 : : : "eax"); /* Tell GCC we destroyed eax. */
20}
diff --git a/pintos-progos/tests/vm/pt-grow-pusha.ck b/pintos-progos/tests/vm/pt-grow-pusha.ck
new file mode 100644
index 0000000..5000966
--- /dev/null
+++ b/pintos-progos/tests/vm/pt-grow-pusha.ck
@@ -0,0 +1,9 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(pt-grow-pusha) begin
7(pt-grow-pusha) end
8EOF
9pass;
diff --git a/pintos-progos/tests/vm/pt-grow-stack.c b/pintos-progos/tests/vm/pt-grow-stack.c
new file mode 100644
index 0000000..0997a00
--- /dev/null
+++ b/pintos-progos/tests/vm/pt-grow-stack.c
@@ -0,0 +1,20 @@
1/* Demonstrate that the stack can grow.
2 This must succeed. */
3
4#include <string.h>
5#include "tests/arc4.h"
6#include "tests/cksum.h"
7#include "tests/lib.h"
8#include "tests/main.h"
9
10void
11test_main (void)
12{
13 char stack_obj[4096];
14 struct arc4 arc4;
15
16 arc4_init (&arc4, "foobar", 6);
17 memset (stack_obj, 0, sizeof stack_obj);
18 arc4_crypt (&arc4, stack_obj, sizeof stack_obj);
19 msg ("cksum: %lu", cksum (stack_obj, sizeof stack_obj));
20}
diff --git a/pintos-progos/tests/vm/pt-grow-stack.ck b/pintos-progos/tests/vm/pt-grow-stack.ck
new file mode 100644
index 0000000..1e669db
--- /dev/null
+++ b/pintos-progos/tests/vm/pt-grow-stack.ck
@@ -0,0 +1,10 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(pt-grow-stack) begin
7(pt-grow-stack) cksum: 3424492700
8(pt-grow-stack) end
9EOF
10pass;
diff --git a/pintos-progos/tests/vm/pt-grow-stk-sc.c b/pintos-progos/tests/vm/pt-grow-stk-sc.c
new file mode 100644
index 0000000..3efbb5f
--- /dev/null
+++ b/pintos-progos/tests/vm/pt-grow-stk-sc.c
@@ -0,0 +1,32 @@
1/* This test checks that the stack is properly extended even if
2 the first access to a stack location occurs inside a system
3 call.
4
5 From Godmar Back. */
6
7#include <string.h>
8#include <syscall.h>
9#include "tests/vm/sample.inc"
10#include "tests/lib.h"
11#include "tests/main.h"
12
13void
14test_main (void)
15{
16 int handle;
17 int slen = strlen (sample);
18 char buf2[65536];
19
20 /* Write file via write(). */
21 CHECK (create ("sample.txt", slen), "create \"sample.txt\"");
22 CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
23 CHECK (write (handle, sample, slen) == slen, "write \"sample.txt\"");
24 close (handle);
25
26 /* Read back via read(). */
27 CHECK ((handle = open ("sample.txt")) > 1, "2nd open \"sample.txt\"");
28 CHECK (read (handle, buf2 + 32768, slen) == slen, "read \"sample.txt\"");
29
30 CHECK (!memcmp (sample, buf2 + 32768, slen), "compare written data against read data");
31 close (handle);
32}
diff --git a/pintos-progos/tests/vm/pt-grow-stk-sc.ck b/pintos-progos/tests/vm/pt-grow-stk-sc.ck
new file mode 100644
index 0000000..23d3b02
--- /dev/null
+++ b/pintos-progos/tests/vm/pt-grow-stk-sc.ck
@@ -0,0 +1,15 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(pt-grow-stk-sc) begin
7(pt-grow-stk-sc) create "sample.txt"
8(pt-grow-stk-sc) open "sample.txt"
9(pt-grow-stk-sc) write "sample.txt"
10(pt-grow-stk-sc) 2nd open "sample.txt"
11(pt-grow-stk-sc) read "sample.txt"
12(pt-grow-stk-sc) compare written data against read data
13(pt-grow-stk-sc) end
14EOF
15pass;
diff --git a/pintos-progos/tests/vm/pt-write-code-2.c b/pintos-progos/tests/vm/pt-write-code-2.c
new file mode 100644
index 0000000..83bcc2c
--- /dev/null
+++ b/pintos-progos/tests/vm/pt-write-code-2.c
@@ -0,0 +1,15 @@
1/* Try to write to the code segment using a system call.
2 The process must be terminated with -1 exit code. */
3
4#include "tests/lib.h"
5#include "tests/main.h"
6
7void
8test_main (void)
9{
10 int handle;
11
12 CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
13 read (handle, (void *) test_main, 1);
14 fail ("survived reading data into code segment");
15}
diff --git a/pintos-progos/tests/vm/pt-write-code.c b/pintos-progos/tests/vm/pt-write-code.c
new file mode 100644
index 0000000..5072cec
--- /dev/null
+++ b/pintos-progos/tests/vm/pt-write-code.c
@@ -0,0 +1,12 @@
1/* Try to write to the code segment.
2 The process must be terminated with -1 exit code. */
3
4#include "tests/lib.h"
5#include "tests/main.h"
6
7void
8test_main (void)
9{
10 *(int *) test_main = 0;
11 fail ("writing the code segment succeeded");
12}
diff --git a/pintos-progos/tests/vm/pt-write-code.ck b/pintos-progos/tests/vm/pt-write-code.ck
new file mode 100644
index 0000000..65610fb
--- /dev/null
+++ b/pintos-progos/tests/vm/pt-write-code.ck
@@ -0,0 +1,7 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5use tests::vm::process_death;
6
7check_process_death ('pt-write-code');
diff --git a/pintos-progos/tests/vm/pt-write-code2.ck b/pintos-progos/tests/vm/pt-write-code2.ck
new file mode 100644
index 0000000..69ffc77
--- /dev/null
+++ b/pintos-progos/tests/vm/pt-write-code2.ck
@@ -0,0 +1,10 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF']);
6(pt-write-code2) begin
7(pt-write-code2) open "sample.txt"
8pt-write-code2: exit(-1)
9EOF
10pass;
diff --git a/pintos-progos/tests/vm/qsort.c b/pintos-progos/tests/vm/qsort.c
new file mode 100644
index 0000000..922572c
--- /dev/null
+++ b/pintos-progos/tests/vm/qsort.c
@@ -0,0 +1,136 @@
1#include "tests/vm/qsort.h"
2#include <stdbool.h>
3#include <debug.h>
4#include <random.h>
5
6/* Picks a pivot for the quicksort from the SIZE bytes in BUF. */
7static unsigned char
8pick_pivot (unsigned char *buf, size_t size)
9{
10 ASSERT (size >= 1);
11 return buf[random_ulong () % size];
12}
13
14/* Checks whether the SIZE bytes in ARRAY are divided into an
15 initial LEFT_SIZE elements all less than PIVOT followed by
16 SIZE - LEFT_SIZE elements all greater than or equal to
17 PIVOT. */
18static bool
19is_partitioned (const unsigned char *array, size_t size,
20 unsigned char pivot, size_t left_size)
21{
22 size_t i;
23
24 for (i = 0; i < left_size; i++)
25 if (array[i] >= pivot)
26 return false;
27
28 for (; i < size; i++)
29 if (array[i] < pivot)
30 return false;
31
32 return true;
33}
34
35/* Swaps the bytes at *A and *B. */
36static void
37swap (unsigned char *a, unsigned char *b)
38{
39 unsigned char t = *a;
40 *a = *b;
41 *b = t;
42}
43
44/* Partitions ARRAY in-place in an initial run of bytes all less
45 than PIVOT, followed by a run of bytes all greater than or
46 equal to PIVOT. Returns the length of the initial run. */
47static size_t
48partition (unsigned char *array, size_t size, int pivot)
49{
50 size_t left_size = size;
51 unsigned char *first = array;
52 unsigned char *last = first + left_size;
53
54 for (;;)
55 {
56 /* Move FIRST forward to point to first element greater than
57 PIVOT. */
58 for (;;)
59 {
60 if (first == last)
61 {
62 ASSERT (is_partitioned (array, size, pivot, left_size));
63 return left_size;
64 }
65 else if (*first >= pivot)
66 break;
67
68 first++;
69 }
70 left_size--;
71
72 /* Move LAST backward to point to last element no bigger
73 than PIVOT. */
74 for (;;)
75 {
76 last--;
77
78 if (first == last)
79 {
80 ASSERT (is_partitioned (array, size, pivot, left_size));
81 return left_size;
82 }
83 else if (*last < pivot)
84 break;
85 else
86 left_size--;
87 }
88
89 /* By swapping FIRST and LAST we extend the starting and
90 ending sequences that pass and fail, respectively,
91 PREDICATE. */
92 swap (first, last);
93 first++;
94 }
95}
96
97/* Returns true if the SIZE bytes in BUF are in nondecreasing
98 order, false otherwise. */
99static bool
100is_sorted (const unsigned char *buf, size_t size)
101{
102 size_t i;
103
104 for (i = 1; i < size; i++)
105 if (buf[i - 1] > buf[i])
106 return false;
107
108 return true;
109}
110
111/* Sorts the SIZE bytes in BUF into nondecreasing order, using
112 the quick-sort algorithm. */
113void
114qsort_bytes (unsigned char *buf, size_t size)
115{
116 if (!is_sorted (buf, size))
117 {
118 int pivot = pick_pivot (buf, size);
119
120 unsigned char *left_half = buf;
121 size_t left_size = partition (buf, size, pivot);
122 unsigned char *right_half = left_half + left_size;
123 size_t right_size = size - left_size;
124
125 if (left_size <= right_size)
126 {
127 qsort_bytes (left_half, left_size);
128 qsort_bytes (right_half, right_size);
129 }
130 else
131 {
132 qsort_bytes (right_half, right_size);
133 qsort_bytes (left_half, left_size);
134 }
135 }
136}
diff --git a/pintos-progos/tests/vm/qsort.h b/pintos-progos/tests/vm/qsort.h
new file mode 100644
index 0000000..61b65f3
--- /dev/null
+++ b/pintos-progos/tests/vm/qsort.h
@@ -0,0 +1,8 @@
1#ifndef TESTS_VM_QSORT_H
2#define TESTS_VM_QSORT_H 1
3
4#include <stddef.h>
5
6void qsort_bytes (unsigned char *buf, size_t size);
7
8#endif /* tests/vm/qsort.h */
diff --git a/pintos-progos/tests/vm/sample.inc b/pintos-progos/tests/vm/sample.inc
new file mode 100644
index 0000000..a60a139
--- /dev/null
+++ b/pintos-progos/tests/vm/sample.inc
@@ -0,0 +1,19 @@
1char sample[] = {
2 "=== ALL USERS PLEASE NOTE ========================\n"
3 "\n"
4 "CAR and CDR now return extra values.\n"
5 "\n"
6 "The function CAR now returns two values. Since it has to go to the\n"
7 "trouble to figure out if the object is carcdr-able anyway, we figured\n"
8 "you might as well get both halves at once. For example, the following\n"
9 "code shows how to destructure a cons (SOME-CONS) into its two slots\n"
10 "(THE-CAR and THE-CDR):\n"
11 "\n"
12 " (MULTIPLE-VALUE-BIND (THE-CAR THE-CDR) (CAR SOME-CONS) ...)\n"
13 "\n"
14 "For symmetry with CAR, CDR returns a second value which is the CAR of\n"
15 "the object. In a related change, the functions MAKE-ARRAY and CONS\n"
16 "have been fixed so they don't allocate any storage except on the\n"
17 "stack. This should hopefully help people who don't like using the\n"
18 "garbage collector because it cold boots the machine so often.\n"
19};
diff --git a/pintos-progos/tests/vm/sample.txt b/pintos-progos/tests/vm/sample.txt
new file mode 100644
index 0000000..c446830
--- /dev/null
+++ b/pintos-progos/tests/vm/sample.txt
@@ -0,0 +1,17 @@
1=== ALL USERS PLEASE NOTE ========================
2
3CAR and CDR now return extra values.
4
5The function CAR now returns two values. Since it has to go to the
6trouble to figure out if the object is carcdr-able anyway, we figured
7you might as well get both halves at once. For example, the following
8code shows how to destructure a cons (SOME-CONS) into its two slots
9(THE-CAR and THE-CDR):
10
11 (MULTIPLE-VALUE-BIND (THE-CAR THE-CDR) (CAR SOME-CONS) ...)
12
13For symmetry with CAR, CDR returns a second value which is the CAR of
14the object. In a related change, the functions MAKE-ARRAY and CONS
15have been fixed so they don't allocate any storage except on the
16stack. This should hopefully help people who don't like using the
17garbage collector because it cold boots the machine so often.