provided code

This commit is contained in:
LabTS
2024-10-01 23:37:39 +01:00
commit 8724a2641e
697 changed files with 74252 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
# Percentage of the testing point total designated for each set of tests.
# This task is primarily about implementing system calls.
# If you do so properly, the base file system functionality should
# come "for free". Thus, the points emphasis below.
40% tests/userprog/Rubric.functionality
30% tests/userprog/Rubric.robustness
0% tests/userprog/Rubric.robustnessCR
10% tests/userprog/no-vm/Rubric
20% tests/filesys/base/Rubric

View File

@@ -0,0 +1,148 @@
# -*- makefile -*-
tests/%.output: FILESYSSOURCE = --filesys-size=2
tests/%.output: PUTFILES = $(filter-out kernel.bin loader.bin, $^)
tests/userprog_TESTS = $(addprefix tests/userprog/,args-none \
args-single args-multiple args-many args-dbl-space sc-bad-sp \
sc-bad-arg sc-bad-num sc-boundary sc-boundary-2 halt exit create-normal \
create-empty create-null create-bad-ptr create-long create-exists \
create-bound open-normal open-missing open-boundary open-empty \
open-null open-bad-ptr open-twice close-normal close-twice close-stdin \
close-stdout close-bad-fd read-normal read-bad-ptr read-boundary \
read-zero read-stdout read-bad-fd write-normal write-bad-ptr \
write-boundary write-zero write-stdin write-bad-fd exec-once exec-arg \
exec-large-arg exec-multiple exec-missing exec-over-arg exec-over-args \
exec-bad-ptr wait-simple wait-twice wait-killed wait-load-kill \
wait-bad-pid wait-bad-child multi-recurse multi-child-fd rox-simple \
rox-child rox-multichild bad-read bad-write bad-read2 bad-write2 \
bad-jump bad-jump2 bad-maths)
tests/userprog_PROGS = $(tests/userprog_TESTS) $(addprefix \
tests/userprog/,child-simple child-args child-bad child-close child-rox exec-exit)
tests/userprog/args-none_SRC = tests/userprog/args.c
tests/userprog/args-single_SRC = tests/userprog/args.c
tests/userprog/args-multiple_SRC = tests/userprog/args.c
tests/userprog/args-many_SRC = tests/userprog/args.c
tests/userprog/args-dbl-space_SRC = tests/userprog/args.c
tests/userprog/sc-bad-sp_SRC = tests/userprog/sc-bad-sp.c tests/main.c
tests/userprog/sc-bad-arg_SRC = tests/userprog/sc-bad-arg.c tests/main.c
tests/userprog/sc-bad-num_SRC = tests/userprog/sc-bad-num.c tests/main.c
tests/userprog/bad-read_SRC = tests/userprog/bad-read.c tests/main.c
tests/userprog/bad-write_SRC = tests/userprog/bad-write.c tests/main.c
tests/userprog/bad-jump_SRC = tests/userprog/bad-jump.c tests/main.c
tests/userprog/bad-read2_SRC = tests/userprog/bad-read2.c tests/main.c
tests/userprog/bad-write2_SRC = tests/userprog/bad-write2.c tests/main.c
tests/userprog/bad-jump2_SRC = tests/userprog/bad-jump2.c tests/main.c
tests/userprog/bad-maths_SRC = tests/userprog/bad-maths.c tests/main.c
tests/userprog/sc-boundary_SRC = tests/userprog/sc-boundary.c \
tests/userprog/boundary.c tests/main.c
tests/userprog/sc-boundary-2_SRC = tests/userprog/sc-boundary-2.c \
tests/userprog/boundary.c tests/main.c
tests/userprog/halt_SRC = tests/userprog/halt.c tests/main.c
tests/userprog/exit_SRC = tests/userprog/exit.c tests/main.c
tests/userprog/create-normal_SRC = tests/userprog/create-normal.c tests/main.c
tests/userprog/create-empty_SRC = tests/userprog/create-empty.c tests/main.c
tests/userprog/create-null_SRC = tests/userprog/create-null.c tests/main.c
tests/userprog/create-bad-ptr_SRC = tests/userprog/create-bad-ptr.c \
tests/main.c
tests/userprog/create-long_SRC = tests/userprog/create-long.c tests/main.c
tests/userprog/create-exists_SRC = tests/userprog/create-exists.c tests/main.c
tests/userprog/create-bound_SRC = tests/userprog/create-bound.c \
tests/userprog/boundary.c tests/main.c
tests/userprog/open-normal_SRC = tests/userprog/open-normal.c tests/main.c
tests/userprog/open-missing_SRC = tests/userprog/open-missing.c tests/main.c
tests/userprog/open-boundary_SRC = tests/userprog/open-boundary.c \
tests/userprog/boundary.c tests/main.c
tests/userprog/open-empty_SRC = tests/userprog/open-empty.c tests/main.c
tests/userprog/open-null_SRC = tests/userprog/open-null.c tests/main.c
tests/userprog/open-bad-ptr_SRC = tests/userprog/open-bad-ptr.c tests/main.c
tests/userprog/open-twice_SRC = tests/userprog/open-twice.c tests/main.c
tests/userprog/close-normal_SRC = tests/userprog/close-normal.c tests/main.c
tests/userprog/close-twice_SRC = tests/userprog/close-twice.c tests/main.c
tests/userprog/close-stdin_SRC = tests/userprog/close-stdin.c tests/main.c
tests/userprog/close-stdout_SRC = tests/userprog/close-stdout.c tests/main.c
tests/userprog/close-bad-fd_SRC = tests/userprog/close-bad-fd.c tests/main.c
tests/userprog/read-normal_SRC = tests/userprog/read-normal.c tests/main.c
tests/userprog/read-bad-ptr_SRC = tests/userprog/read-bad-ptr.c tests/main.c
tests/userprog/read-boundary_SRC = tests/userprog/read-boundary.c \
tests/userprog/boundary.c tests/main.c
tests/userprog/read-zero_SRC = tests/userprog/read-zero.c tests/main.c
tests/userprog/read-stdout_SRC = tests/userprog/read-stdout.c tests/main.c
tests/userprog/read-bad-fd_SRC = tests/userprog/read-bad-fd.c tests/main.c
tests/userprog/write-normal_SRC = tests/userprog/write-normal.c tests/main.c
tests/userprog/write-bad-ptr_SRC = tests/userprog/write-bad-ptr.c tests/main.c
tests/userprog/write-boundary_SRC = tests/userprog/write-boundary.c \
tests/userprog/boundary.c tests/main.c
tests/userprog/write-zero_SRC = tests/userprog/write-zero.c tests/main.c
tests/userprog/write-stdin_SRC = tests/userprog/write-stdin.c tests/main.c
tests/userprog/write-bad-fd_SRC = tests/userprog/write-bad-fd.c tests/main.c
tests/userprog/exec-once_SRC = tests/userprog/exec-once.c tests/main.c
tests/userprog/exec-arg_SRC = tests/userprog/exec-arg.c tests/main.c
tests/userprog/exec-large-arg_SRC = tests/userprog/exec-large-arg.c tests/main.c
tests/userprog/exec-multiple_SRC = tests/userprog/exec-multiple.c tests/main.c
tests/userprog/exec-missing_SRC = tests/userprog/exec-missing.c tests/main.c
tests/userprog/exec-over-arg_SRC = tests/userprog/exec-over-arg.c tests/main.c
tests/userprog/exec-over-args_SRC = tests/userprog/exec-over-args.c tests/main.c
tests/userprog/exec-bad-ptr_SRC = tests/userprog/exec-bad-ptr.c tests/main.c
tests/userprog/wait-simple_SRC = tests/userprog/wait-simple.c tests/main.c
tests/userprog/wait-twice_SRC = tests/userprog/wait-twice.c tests/main.c
tests/userprog/wait-killed_SRC = tests/userprog/wait-killed.c tests/main.c
tests/userprog/wait-load-kill_SRC = tests/userprog/wait-load-kill.c tests/main.c
tests/userprog/wait-bad-pid_SRC = tests/userprog/wait-bad-pid.c tests/main.c
tests/userprog/wait-bad-child_SRC = tests/userprog/wait-bad-child.c tests/main.c
tests/userprog/multi-recurse_SRC = tests/userprog/multi-recurse.c
tests/userprog/multi-child-fd_SRC = tests/userprog/multi-child-fd.c \
tests/main.c
tests/userprog/rox-simple_SRC = tests/userprog/rox-simple.c tests/main.c
tests/userprog/rox-child_SRC = tests/userprog/rox-child.c tests/main.c
tests/userprog/rox-multichild_SRC = tests/userprog/rox-multichild.c \
tests/main.c
tests/userprog/child-simple_SRC = tests/userprog/child-simple.c
tests/userprog/child-args_SRC = tests/userprog/args.c
tests/userprog/child-bad_SRC = tests/userprog/child-bad.c tests/main.c
tests/userprog/child-close_SRC = tests/userprog/child-close.c
tests/userprog/child-rox_SRC = tests/userprog/child-rox.c
tests/userprog/exec-exit_SRC = tests/userprog/exec-exit.c
$(foreach prog,$(tests/userprog_PROGS),$(eval $(prog)_SRC += tests/lib.c))
tests/userprog/args-single_ARGS = onearg
tests/userprog/args-multiple_ARGS = some arguments for you!
tests/userprog/args-many_ARGS = a b c d e f g h i j k l m n o p q r s t u v
tests/userprog/args-dbl-space_ARGS = two spaces!
tests/userprog/multi-recurse_ARGS = 15
tests/userprog/open-normal_PUTFILES += tests/userprog/sample.txt
tests/userprog/open-boundary_PUTFILES += tests/userprog/sample.txt
tests/userprog/open-twice_PUTFILES += tests/userprog/sample.txt
tests/userprog/close-normal_PUTFILES += tests/userprog/sample.txt
tests/userprog/close-twice_PUTFILES += tests/userprog/sample.txt
tests/userprog/read-normal_PUTFILES += tests/userprog/sample.txt
tests/userprog/read-bad-ptr_PUTFILES += tests/userprog/sample.txt
tests/userprog/read-boundary_PUTFILES += tests/userprog/sample.txt
tests/userprog/read-zero_PUTFILES += tests/userprog/sample.txt
tests/userprog/write-normal_PUTFILES += tests/userprog/sample.txt
tests/userprog/write-bad-ptr_PUTFILES += tests/userprog/sample.txt
tests/userprog/write-boundary_PUTFILES += tests/userprog/sample.txt
tests/userprog/write-zero_PUTFILES += tests/userprog/sample.txt
tests/userprog/multi-child-fd_PUTFILES += tests/userprog/sample.txt
tests/userprog/exec-once_PUTFILES += tests/userprog/child-simple
tests/userprog/exec-multiple_PUTFILES += tests/userprog/child-simple
tests/userprog/wait-simple_PUTFILES += tests/userprog/child-simple
tests/userprog/wait-twice_PUTFILES += tests/userprog/child-simple
tests/userprog/exec-arg_PUTFILES += tests/userprog/child-args
tests/userprog/exec-large-arg_PUTFILES += tests/userprog/child-args
tests/userprog/exec-over-arg_PUTFILES += tests/userprog/child-args
tests/userprog/exec-over-args_PUTFILES += tests/userprog/child-args
tests/userprog/multi-child-fd_PUTFILES += tests/userprog/child-close
tests/userprog/wait-killed_PUTFILES += tests/userprog/child-bad
tests/userprog/wait-load-kill_PUTFILES += tests/userprog/child-bad
tests/userprog/wait-bad-child_PUTFILES += tests/userprog/exec-exit
tests/userprog/wait-bad-child_PUTFILES += tests/userprog/child-simple
tests/userprog/rox-child_PUTFILES += tests/userprog/child-rox
tests/userprog/rox-multichild_PUTFILES += tests/userprog/child-rox

View File

@@ -0,0 +1,55 @@
Functionality of system calls:
- Test argument passing on PintOS command line.
3 args-none
3 args-single
3 args-multiple
3 args-many
3 args-dbl-space
- Test "create" system call.
3 create-empty
3 create-long
3 create-normal
3 create-exists
- Test "open" system call.
3 open-missing
3 open-normal
3 open-twice
- Test "read" system call.
3 read-normal
3 read-zero
- Test "write" system call.
3 write-normal
3 write-zero
- Test "close" system call.
3 close-normal
- Test "exec" system call.
5 exec-once
5 exec-multiple
5 exec-arg
5 exec-large-arg
- Test "wait" system call.
5 wait-simple
5 wait-killed
5 wait-twice
5 wait-bad-child
- Test "exit" system call.
5 exit
- Test "halt" system call.
3 halt
- Test recursive execution of user programs.
15 multi-recurse
- Test read-only executable feature.
3 rox-simple
3 rox-child
3 rox-multichild

View File

@@ -0,0 +1,50 @@
Robustness of system calls:
- Test robustness of file descriptor handling.
2 close-stdin
2 close-stdout
2 close-bad-fd
2 close-twice
2 read-bad-fd
2 read-stdout
2 write-bad-fd
2 write-stdin
2 multi-child-fd
- Test robustness of pointer handling.
3 create-bad-ptr
3 exec-bad-ptr
3 open-bad-ptr
3 read-bad-ptr
3 write-bad-ptr
- Test robustness of buffer copying across page boundaries.
3 create-bound
3 open-boundary
3 read-boundary
3 write-boundary
- Test handling of null pointer and empty strings.
2 create-null
2 open-null
2 open-empty
- Test robustness of system call implementation.
3 sc-bad-arg
3 sc-bad-sp
3 sc-bad-num
3 sc-boundary
3 sc-boundary-2
- Test robustness of "exec" and "wait" system calls.
5 exec-missing
5 wait-bad-pid
5 wait-load-kill
- Test robustness of exception handling.
1 bad-read
1 bad-write
1 bad-jump
1 bad-read2
1 bad-write2
1 bad-jump2
1 bad-maths

View File

@@ -0,0 +1,5 @@
Full robustness of argument passing code:
- Test user stack overflow robustness of "exec" system calls.
5 exec-over-arg
5 exec-over-args

View File

@@ -0,0 +1,15 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF']);
(args) begin
(args) argc = 3
(args) argv[0] = 'args-dbl-space'
(args) argv[1] = 'two'
(args) argv[2] = 'spaces!'
(args) argv[3] = null
(args) end
args-dbl-space: exit(0)
EOF
pass;

View File

@@ -0,0 +1,35 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF']);
(args) begin
(args) argc = 23
(args) argv[0] = 'args-many'
(args) argv[1] = 'a'
(args) argv[2] = 'b'
(args) argv[3] = 'c'
(args) argv[4] = 'd'
(args) argv[5] = 'e'
(args) argv[6] = 'f'
(args) argv[7] = 'g'
(args) argv[8] = 'h'
(args) argv[9] = 'i'
(args) argv[10] = 'j'
(args) argv[11] = 'k'
(args) argv[12] = 'l'
(args) argv[13] = 'm'
(args) argv[14] = 'n'
(args) argv[15] = 'o'
(args) argv[16] = 'p'
(args) argv[17] = 'q'
(args) argv[18] = 'r'
(args) argv[19] = 's'
(args) argv[20] = 't'
(args) argv[21] = 'u'
(args) argv[22] = 'v'
(args) argv[23] = null
(args) end
args-many: exit(0)
EOF
pass;

View File

@@ -0,0 +1,17 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF']);
(args) begin
(args) argc = 5
(args) argv[0] = 'args-multiple'
(args) argv[1] = 'some'
(args) argv[2] = 'arguments'
(args) argv[3] = 'for'
(args) argv[4] = 'you!'
(args) argv[5] = null
(args) end
args-multiple: exit(0)
EOF
pass;

View File

@@ -0,0 +1,13 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF']);
(args) begin
(args) argc = 1
(args) argv[0] = 'args-none'
(args) argv[1] = null
(args) end
args-none: exit(0)
EOF
pass;

View File

@@ -0,0 +1,14 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF']);
(args) begin
(args) argc = 2
(args) argv[0] = 'args-single'
(args) argv[1] = 'onearg'
(args) argv[2] = null
(args) end
args-single: exit(0)
EOF
pass;

25
src/tests/userprog/args.c Normal file
View File

@@ -0,0 +1,25 @@
/* Prints the command-line arguments.
This program is used for all of the args-* tests. Grading is
done differently for each of the args-* tests based on the
output. */
#include "tests/lib.h"
int
main (int argc, char *argv[])
{
int i;
test_name = "args";
msg ("begin");
msg ("argc = %d", argc);
for (i = 0; i <= argc; i++)
if (argv[i] != NULL)
msg ("argv[%d] = '%s'", i, argv[i]);
else
msg ("argv[%d] = null", i);
msg ("end");
return 0;
}

View File

@@ -0,0 +1,13 @@
/* This program attempts to execute code at address 0, which is not mapped.
This should terminate the process with a -1 exit code. */
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
msg ("Congratulations - you have successfully called NULL: %d",
((int (*)(void))NULL)());
fail ("should have exited with -1");
}

View File

@@ -0,0 +1,9 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']);
(bad-jump) begin
bad-jump: exit(-1)
EOF
pass;

View File

@@ -0,0 +1,13 @@
/* This program attempts to execute code at a kernel virtual address.
This should terminate the process with a -1 exit code. */
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
msg ("Congratulations - you have successfully called kernel code: %d",
((int (*)(void))0xC0000000)());
fail ("should have exited with -1");
}

View File

@@ -0,0 +1,9 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']);
(bad-jump2) begin
bad-jump2: exit(-1)
EOF
pass;

View File

@@ -0,0 +1,12 @@
/* This program attempts to divide by zero, which will trigger an internal interrupt.
This should terminate the process with a -1 exit code. */
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
msg ("Congratulations - you have successfully divided by zero: %d", 1/0);
fail ("should have exited with -1");
}

View File

@@ -0,0 +1,9 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected (IGNORE_DIV0_FAULTS => 1, [<<'EOF']);
(bad-maths) begin
bad-maths: exit(-1)
EOF
pass;

View File

@@ -0,0 +1,13 @@
/* This program attempts to read memory at an address that is not mapped.
This should terminate the process with a -1 exit code. */
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
msg ("Congratulations - you have successfully dereferenced NULL: %d",
*(int *)NULL);
fail ("should have exited with -1");
}

View File

@@ -0,0 +1,9 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']);
(bad-read) begin
bad-read: exit(-1)
EOF
pass;

View File

@@ -0,0 +1,13 @@
/* This program attempts to read kernel memory.
This should terminate the process with a -1 exit code. */
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
msg ("Congratulations - you have successfully read kernel memory: %d",
*(int *)0xC0000000);
fail ("should have exited with -1");
}

View File

@@ -0,0 +1,9 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']);
(bad-read2) begin
bad-read2: exit(-1)
EOF
pass;

View File

@@ -0,0 +1,12 @@
/* This program attempts to write to memory at an address that is not mapped.
This should terminate the process with a -1 exit code. */
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
*(int *)NULL = 42;
fail ("should have exited with -1");
}

View File

@@ -0,0 +1,9 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']);
(bad-write) begin
bad-write: exit(-1)
EOF
pass;

View File

@@ -0,0 +1,12 @@
/* This program attempts to write to kernel memory.
This should terminate the process with a -1 exit code. */
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
*(int *)0xC0000000 = 42;
fail ("should have exited with -1");
}

View File

@@ -0,0 +1,9 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected (IGNORE_USER_FAULTS => 1, [<<'EOF']);
(bad-write2) begin
bad-write2: exit(-1)
EOF
pass;

View File

@@ -0,0 +1,33 @@
/* Utility function for tests that try to break system calls by
passing them data that crosses from one virtual page to
another. */
#include <inttypes.h>
#include <round.h>
#include <string.h>
#include "tests/userprog/boundary.h"
static char dst[8192];
/* Returns the beginning of a page. There are at least 2048
modifiable bytes on either side of the pointer returned. */
void *
get_boundary_area (void)
{
char *p = (char *) ROUND_UP ((uintptr_t) dst, 4096);
if (p - dst < 2048)
p += 4096;
return p;
}
/* Returns a copy of SRC split across the boundary between two
pages. */
char *
copy_string_across_boundary (const char *src)
{
char *p = get_boundary_area ();
p -= strlen (src) < 4096 ? strlen (src) / 2 : 4096;
strlcpy (p, src, 4096);
return p;
}

View File

@@ -0,0 +1,7 @@
#ifndef TESTS_USERPROG_BOUNDARY_H
#define TESTS_USERPROG_BOUNDARY_H
void *get_boundary_area (void);
char *copy_string_across_boundary (const char *);
#endif /* tests/userprog/boundary.h */

View File

@@ -0,0 +1,14 @@
/* Child process run by wait-killed test.
Sets the stack pointer (%esp) to an invalid value and invokes
a system call, which should then terminate the process with a
-1 exit code. */
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
asm volatile ("movl $0x20101234, %esp; int $0x30");
fail ("should have exited with -1");
}

View File

@@ -0,0 +1,28 @@
/* Child process run by multi-child-fd test.
Attempts to close the file descriptor passed as the first
command-line argument. This is invalid, because file
descriptors are not inherited in PintOS. Two results are
allowed: either the system call should return without taking
any action, or the kernel should terminate the process with a
-1 exit code. */
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <syscall.h>
#include "tests/lib.h"
const char *test_name = "child-close";
int
main (int argc UNUSED, char *argv[])
{
msg ("begin");
if (!isdigit (*argv[1]))
fail ("bad command-line arguments");
close (atoi (argv[1]));
msg ("end");
return 0;
}

View File

@@ -0,0 +1,55 @@
/* Child process run by rox-child and rox-multichild tests.
Opens and tries to write to its own executable, verifying that
that is disallowed.
Then recursively executes itself to the depth indicated by the
first command-line argument. */
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <syscall.h>
#include "tests/lib.h"
const char *test_name = "child-rox";
static void
try_write (void)
{
int handle;
char buffer[19];
quiet = true;
CHECK ((handle = open ("child-rox")) > 1, "open \"child-rox\"");
quiet = false;
CHECK (write (handle, buffer, sizeof buffer) == 0,
"try to write \"child-rox\"");
close (handle);
}
int
main (int argc UNUSED, char *argv[])
{
msg ("begin");
try_write ();
if (!isdigit (*argv[1]))
fail ("bad command-line arguments");
if (atoi (argv[1]) > 1)
{
char cmd[128];
int child;
snprintf (cmd, sizeof cmd, "child-rox %d", atoi (argv[1]) - 1);
CHECK ((child = exec (cmd)) != -1, "exec \"%s\"", cmd);
quiet = true;
CHECK (wait (child) == 12, "wait for \"child-rox\"");
quiet = false;
}
try_write ();
msg ("end");
return 12;
}

View File

@@ -0,0 +1,15 @@
/* Child process run by exec-multiple, exec-one, wait-simple, and
wait-twice tests.
Just prints a single message and terminates. */
#include <stdio.h>
#include "tests/lib.h"
const char *test_name = "child-simple";
int
main (void)
{
msg ("run");
return 81;
}

View File

@@ -0,0 +1,11 @@
/* Tries to close an invalid fd, which must either fail silently
or terminate with exit code -1. */
#include <syscall.h>
#include "tests/main.h"
void
test_main (void)
{
close (0x20101234);
}

View File

@@ -0,0 +1,13 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF', <<'EOF']);
(close-bad-fd) begin
(close-bad-fd) end
close-bad-fd: exit(0)
EOF
(close-bad-fd) begin
close-bad-fd: exit(-1)
EOF
pass;

View File

@@ -0,0 +1,14 @@
/* Opens a file and then closes it. */
#include <syscall.h>
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
int handle;
CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
msg ("close \"sample.txt\"");
close (handle);
}

View File

@@ -0,0 +1,12 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF']);
(close-normal) begin
(close-normal) open "sample.txt"
(close-normal) close "sample.txt"
(close-normal) end
close-normal: exit(0)
EOF
pass;

View File

@@ -0,0 +1,11 @@
/* Tries to close the keyboard input stream, which must either
fail silently or terminate with exit code -1. */
#include <syscall.h>
#include "tests/main.h"
void
test_main (void)
{
close (0);
}

View File

@@ -0,0 +1,13 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF', <<'EOF']);
(close-stdin) begin
(close-stdin) end
close-stdin: exit(0)
EOF
(close-stdin) begin
close-stdin: exit(-1)
EOF
pass;

View File

@@ -0,0 +1,11 @@
/* Tries to close the console output stream, which must either
fail silently or terminate with exit code -1. */
#include <syscall.h>
#include "tests/main.h"
void
test_main (void)
{
close (1);
}

View File

@@ -0,0 +1,13 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF', <<'EOF']);
(close-stdout) begin
(close-stdout) end
close-stdout: exit(0)
EOF
(close-stdout) begin
close-stdout: exit(-1)
EOF
pass;

View File

@@ -0,0 +1,18 @@
/* Opens a file and then tries to close it twice. The second
close must either fail silently or terminate with exit code
-1. */
#include <syscall.h>
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
int handle;
CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
msg ("close \"sample.txt\"");
close (handle);
msg ("close \"sample.txt\" again");
close (handle);
}

View File

@@ -0,0 +1,19 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF', <<'EOF']);
(close-twice) begin
(close-twice) open "sample.txt"
(close-twice) close "sample.txt"
(close-twice) close "sample.txt" again
(close-twice) end
close-twice: exit(0)
EOF
(close-twice) begin
(close-twice) open "sample.txt"
(close-twice) close "sample.txt"
(close-twice) close "sample.txt" again
close-twice: exit(-1)
EOF
pass;

View File

@@ -0,0 +1,12 @@
/* Passes a bad pointer to the create system call,
which must cause the process to be terminated with exit code
-1. */
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
msg ("create(0x20101234): %d", create ((char *) 0x20101234, 0));
}

View File

@@ -0,0 +1,9 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF']);
(create-bad-ptr) begin
create-bad-ptr: exit(-1)
EOF
pass;

View File

@@ -0,0 +1,14 @@
/* Opens a file whose name spans the boundary between two pages.
This is valid, so it must succeed. */
#include <syscall.h>
#include "tests/userprog/boundary.h"
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
msg ("create(\"quux.dat\"): %d",
create (copy_string_across_boundary ("quux.dat"), 0));
}

View File

@@ -0,0 +1,11 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF']);
(create-bound) begin
(create-bound) create("quux.dat"): 1
(create-bound) end
create-bound: exit(0)
EOF
pass;

View File

@@ -0,0 +1,10 @@
/* Tries to create a file with the empty string as its name. */
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
msg ("create(\"\"): %d", create ("", 0));
}

View File

@@ -0,0 +1,14 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF', <<'EOF']);
(create-empty) begin
(create-empty) create(""): 0
(create-empty) end
create-empty: exit(0)
EOF
(create-empty) begin
create-empty: exit(-1)
EOF
pass;

View File

@@ -0,0 +1,16 @@
/* Verifies that trying to create a file under a name that
already exists will fail. */
#include <syscall.h>
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
CHECK (create ("quux.dat", 0), "create quux.dat");
CHECK (create ("warble.dat", 0), "create warble.dat");
CHECK (!create ("quux.dat", 0), "try to re-create quux.dat");
CHECK (create ("baffle.dat", 0), "create baffle.dat");
CHECK (!create ("warble.dat", 0), "try to re-create warble.dat");
}

View File

@@ -0,0 +1,15 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF']);
(create-exists) begin
(create-exists) create quux.dat
(create-exists) create warble.dat
(create-exists) try to re-create quux.dat
(create-exists) create baffle.dat
(create-exists) try to re-create warble.dat
(create-exists) end
create-exists: exit(0)
EOF
pass;

View File

@@ -0,0 +1,17 @@
/* Tries to create a file with a name that is much too long,
which must fail. */
#include <string.h>
#include <syscall.h>
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
static char name[512];
memset (name, 'x', sizeof name);
name[sizeof name - 1] = '\0';
msg ("create(\"x...\"): %d", create (name, 0));
}

View File

@@ -0,0 +1,11 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF']);
(create-long) begin
(create-long) create("x..."): 0
(create-long) end
create-long: exit(0)
EOF
pass;

View File

@@ -0,0 +1,10 @@
/* Creates an ordinary empty file. */
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
CHECK (create ("quux.dat", 0), "create quux.dat");
}

View File

@@ -0,0 +1,11 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF']);
(create-normal) begin
(create-normal) create quux.dat
(create-normal) end
create-normal: exit(0)
EOF
pass;

View File

@@ -0,0 +1,11 @@
/* Tries to create a file with the null pointer as its name.
The process must be terminated with exit code -1. */
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
msg ("create(NULL): %d", create (NULL, 0));
}

View File

@@ -0,0 +1,9 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF']);
(create-null) begin
create-null: exit(-1)
EOF
pass;

View File

@@ -0,0 +1,10 @@
/* Tests argument passing to child processes. */
#include <syscall.h>
#include "tests/main.h"
void
test_main (void)
{
wait (exec ("child-args childarg"));
}

View File

@@ -0,0 +1,17 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF']);
(exec-arg) begin
(args) begin
(args) argc = 2
(args) argv[0] = 'child-args'
(args) argv[1] = 'childarg'
(args) argv[2] = null
(args) end
child-args: exit(0)
(exec-arg) end
exec-arg: exit(0)
EOF
pass;

View File

@@ -0,0 +1,11 @@
/* Passes an invalid pointer to the exec system call.
The process must be terminated with -1 exit code. */
#include <syscall.h>
#include "tests/main.h"
void
test_main (void)
{
exec ((char *) 0x20101234);
}

View File

@@ -0,0 +1,13 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF', <<'EOF']);
(exec-bad-ptr) begin
(exec-bad-ptr) end
exec-bad-ptr: exit(0)
EOF
(exec-bad-ptr) begin
exec-bad-ptr: exit(-1)
EOF
pass;

View File

@@ -0,0 +1,13 @@
/* Executes and waits for a single child process. */
#include <syscall.h>
#include "tests/lib.h"
const char *test_name = "exec-exit";
int
main (void)
{
msg ("run");
exit (exec ("child-simple"));
}

View File

@@ -0,0 +1,10 @@
/* Tests argument passing to child processes for a single large argument. */
#include <syscall.h>
#include "tests/main.h"
void
test_main (void)
{
wait (exec ("child-args childaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrggggggggggggggggggggggggggggggggggggggggggg!!!!!!!!!!!!!!!!!!!!!!!!!!!.............................."));
}

View File

@@ -0,0 +1,17 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF']);
(exec-large-arg) begin
(args) begin
(args) argc = 2
(args) argv[0] = 'child-args'
(args) argv[1] = 'childaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrggggggggggggggggggggggggggggggggggggggggggg!!!!!!!!!!!!!!!!!!!!!!!!!!!..............................'
(args) argv[2] = null
(args) end
child-args: exit(0)
(exec-large-arg) end
exec-large-arg: exit(0)
EOF
pass;

View File

@@ -0,0 +1,12 @@
/* Tries to execute a nonexistent process.
The exec system call must return -1. */
#include <syscall.h>
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
msg ("exec(\"no-such-file\"): %d", exec ("no-such-file"));
}

View File

@@ -0,0 +1,31 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF', <<'EOF', <<'EOF', <<'EOF']);
(exec-missing) begin
load: no-such-file: open failed
(exec-missing) exec("no-such-file"): -1
(exec-missing) end
exec-missing: exit(0)
EOF
(exec-missing) begin
(exec-missing) exec("no-such-file"): -1
(exec-missing) end
exec-missing: exit(0)
EOF
(exec-missing) begin
load: no-such-file: open failed
no-such-file: exit(-1)
(exec-missing) exec("no-such-file"): -1
(exec-missing) end
exec-missing: exit(0)
EOF
(exec-missing) begin
load: no-such-file: open failed
(exec-missing) exec("no-such-file"): -1
no-such-file: exit(-1)
(exec-missing) end
exec-missing: exit(0)
EOF
pass;

View File

@@ -0,0 +1,14 @@
/* Executes and waits for multiple child processes. */
#include <syscall.h>
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
wait (exec ("child-simple"));
wait (exec ("child-simple"));
wait (exec ("child-simple"));
wait (exec ("child-simple"));
}

View File

@@ -0,0 +1,18 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF']);
(exec-multiple) begin
(child-simple) run
child-simple: exit(81)
(child-simple) run
child-simple: exit(81)
(child-simple) run
child-simple: exit(81)
(child-simple) run
child-simple: exit(81)
(exec-multiple) end
exec-multiple: exit(0)
EOF
pass;

View File

@@ -0,0 +1,11 @@
/* Executes and waits for a single child process. */
#include <syscall.h>
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
wait (exec ("child-simple"));
}

View File

@@ -0,0 +1,12 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF']);
(exec-once) begin
(child-simple) run
child-simple: exit(81)
(exec-once) end
exec-once: exit(0)
EOF
pass;

View File

@@ -0,0 +1,12 @@
/* Tests argument passing stack overflow is handled for a single over-long argument. */
#include <syscall.h>
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
wait (exec ("child-args aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"));
msg ("exec() did not panic the kernel");
}

View File

@@ -0,0 +1,28 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF',<<'EOF',<<'EOF']);
(exec-over-arg) begin
child-args: exit(-1)
(exec-over-arg) exec() did not panic the kernel
(exec-over-arg) end
exec-over-arg: exit(0)
EOF
(exec-over-arg) begin
(exec-over-arg) exec() did not panic the kernel
(exec-over-arg) end
exec-over-arg: exit(0)
EOF
(exec-over-arg) begin
(args) begin
(args) argc = 2
(args) argv[0] = 'child-args'
(args) argv[1] = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(args) argv[2] = null
(args) end
child-args: exit(0)
(exec-over-arg) exec() did not panic the kernel
(exec-over-arg) end
exec-over-arg: exit(0)
EOF
pass;

View File

@@ -0,0 +1,12 @@
/* Tests argument passing stack overflow is handled for 1000 single character arguments. */
#include <syscall.h>
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
wait (exec ("child-args a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r r g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !"));
msg ("exec() did not panic the kernel");
}

File diff suppressed because it is too large Load Diff

11
src/tests/userprog/exit.c Normal file
View File

@@ -0,0 +1,11 @@
/* Tests the exit system call. */
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
exit (57);
fail ("should have called exit(57)");
}

View File

@@ -0,0 +1,9 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF']);
(exit) begin
exit: exit(57)
EOF
pass;

11
src/tests/userprog/halt.c Normal file
View File

@@ -0,0 +1,11 @@
/* Tests the halt system call. */
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
halt ();
fail ("should have halted");
}

View File

@@ -0,0 +1,15 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
our ($test);
my (@output) = read_text_file ("$test.output");
common_checks ("run", @output);
fail "missing 'begin' message\n"
if !grep ($_ eq '(halt) begin', @output);
fail "found 'fail' message--halt didn't really halt\n"
if grep ($_ eq '(halt) fail', @output);
pass;

1
src/tests/userprog/lib/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
*.d

View File

View File

@@ -0,0 +1 @@
*.d

View File

@@ -0,0 +1,25 @@
/* Opens a file and then runs a subprocess that tries to close
the file. (PintOS does not have inheritance of file handles,
so this must fail.) The parent process then attempts to use
the file handle, which must succeed. */
#include <stdio.h>
#include <syscall.h>
#include "tests/userprog/sample.inc"
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
char child_cmd[128];
int handle;
CHECK ((handle = open ("sample.txt")) > 1, "open \"sample.txt\"");
snprintf (child_cmd, sizeof child_cmd, "child-close %d", handle);
msg ("wait(exec()) = %d", wait (exec (child_cmd)));
check_file_handle (handle, "sample.txt", sample, sizeof sample - 1);
}

View File

@@ -0,0 +1,25 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF', <<'EOF']);
(multi-child-fd) begin
(multi-child-fd) open "sample.txt"
(child-close) begin
(child-close) end
child-close: exit(0)
(multi-child-fd) wait(exec()) = 0
(multi-child-fd) verified contents of "sample.txt"
(multi-child-fd) end
multi-child-fd: exit(0)
EOF
(multi-child-fd) begin
(multi-child-fd) open "sample.txt"
(child-close) begin
child-close: exit(-1)
(multi-child-fd) wait(exec()) = -1
(multi-child-fd) verified contents of "sample.txt"
(multi-child-fd) end
multi-child-fd: exit(0)
EOF
pass;

View File

@@ -0,0 +1,34 @@
/* Executes itself recursively to the depth indicated by the
first command-line argument. */
#include <debug.h>
#include <stdlib.h>
#include <stdio.h>
#include <syscall.h>
#include "tests/lib.h"
const char *test_name = "multi-recurse";
int
main (int argc UNUSED, char *argv[])
{
int n = atoi (argv[1]);
msg ("begin %d", n);
if (n != 0)
{
char child_cmd[128];
pid_t child_pid;
int code;
snprintf (child_cmd, sizeof child_cmd, "multi-recurse %d", n - 1);
CHECK ((child_pid = exec (child_cmd)) != -1, "exec(\"%s\")", child_cmd);
code = wait (child_pid);
if (code != n - 1)
fail ("wait(exec(\"%s\")) returned %d", child_cmd, code);
}
msg ("end %d", n);
return n;
}

View File

@@ -0,0 +1,70 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF']);
(multi-recurse) begin 15
(multi-recurse) exec("multi-recurse 14")
(multi-recurse) begin 14
(multi-recurse) exec("multi-recurse 13")
(multi-recurse) begin 13
(multi-recurse) exec("multi-recurse 12")
(multi-recurse) begin 12
(multi-recurse) exec("multi-recurse 11")
(multi-recurse) begin 11
(multi-recurse) exec("multi-recurse 10")
(multi-recurse) begin 10
(multi-recurse) exec("multi-recurse 9")
(multi-recurse) begin 9
(multi-recurse) exec("multi-recurse 8")
(multi-recurse) begin 8
(multi-recurse) exec("multi-recurse 7")
(multi-recurse) begin 7
(multi-recurse) exec("multi-recurse 6")
(multi-recurse) begin 6
(multi-recurse) exec("multi-recurse 5")
(multi-recurse) begin 5
(multi-recurse) exec("multi-recurse 4")
(multi-recurse) begin 4
(multi-recurse) exec("multi-recurse 3")
(multi-recurse) begin 3
(multi-recurse) exec("multi-recurse 2")
(multi-recurse) begin 2
(multi-recurse) exec("multi-recurse 1")
(multi-recurse) begin 1
(multi-recurse) exec("multi-recurse 0")
(multi-recurse) begin 0
(multi-recurse) end 0
multi-recurse: exit(0)
(multi-recurse) end 1
multi-recurse: exit(1)
(multi-recurse) end 2
multi-recurse: exit(2)
(multi-recurse) end 3
multi-recurse: exit(3)
(multi-recurse) end 4
multi-recurse: exit(4)
(multi-recurse) end 5
multi-recurse: exit(5)
(multi-recurse) end 6
multi-recurse: exit(6)
(multi-recurse) end 7
multi-recurse: exit(7)
(multi-recurse) end 8
multi-recurse: exit(8)
(multi-recurse) end 9
multi-recurse: exit(9)
(multi-recurse) end 10
multi-recurse: exit(10)
(multi-recurse) end 11
multi-recurse: exit(11)
(multi-recurse) end 12
multi-recurse: exit(12)
(multi-recurse) end 13
multi-recurse: exit(13)
(multi-recurse) end 14
multi-recurse: exit(14)
(multi-recurse) end 15
multi-recurse: exit(15)
EOF
pass;

View File

@@ -0,0 +1,8 @@
# -*- makefile -*-
tests/userprog/no-vm_TESTS = tests/userprog/no-vm/multi-oom
tests/userprog/no-vm_PROGS = $(tests/userprog/no-vm_TESTS)
tests/userprog/no-vm/multi-oom_SRC = tests/userprog/no-vm/multi-oom.c \
tests/lib.c
tests/userprog/no-vm/multi-oom.output: TIMEOUT = 360

View File

@@ -0,0 +1,3 @@
Functionality of features that VM might break:
10 multi-oom

View File

@@ -0,0 +1,181 @@
/* Recursively executes itself until the child fails to execute.
We expect that at least 30 copies can run.
We count how many children your kernel was able to execute
before it fails to start a new process. We require that,
if a process doesn't actually get to start, exec() must
return -1, not a valid PID.
We repeat this process 10 times, checking that your kernel
allows for the same level of depth every time.
In addition, some processes will spawn children that terminate
abnormally after allocating some resources.
Written by Godmar Back <godmar@gmail.com>
*/
#include <debug.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <syscall.h>
#include <random.h>
#include "tests/lib.h"
static const int EXPECTED_DEPTH_TO_PASS = 30;
static const int EXPECTED_REPETITIONS = 10;
const char *test_name = "multi-oom";
enum child_termination_mode { RECURSE, CRASH };
/* Spawn a recursive copy of ourselves, passing along instructions
for the child. */
static pid_t
spawn_child (int c, enum child_termination_mode mode)
{
char child_cmd[128];
snprintf (child_cmd, sizeof child_cmd,
"%s %d %s", test_name, c, mode == CRASH ? "-k" : "");
return exec (child_cmd);
}
/* Open a number of files (and fail to close them).
The kernel must free any kernel resources associated
with these file descriptors. */
static void
consume_some_resources (void)
{
int fd, fdmax = 126;
/* Open as many files as we can, up to fdmax.
Depending on how file descriptors are allocated inside
the kernel, open() may fail if the kernel is low on memory.
A low-memory condition in open() should not lead to the
termination of the process. */
for (fd = 0; fd < fdmax; fd++)
if (open (test_name) == -1)
break;
}
/* Consume some resources, then terminate this process
in some abnormal way. */
static int NO_INLINE
consume_some_resources_and_die (int seed)
{
consume_some_resources ();
random_init ( (unsigned) seed );
int *PHYS_BASE = (int *)0xC0000000;
switch (random_ulong () % 5)
{
case 0:
*(int *) NULL = 42;
// fall through
case 1:
return *(int *) NULL;
case 2:
return *PHYS_BASE;
case 3:
*PHYS_BASE = 42;
// fall through
case 4:
open ((char *)PHYS_BASE);
exit (-1);
default:
NOT_REACHED ();
}
return 0;
}
/* The first copy is invoked without command line arguments.
Subsequent copies are invoked with a parameter 'depth'
that describes how many parent processes preceded them.
Each process spawns one or multiple recursive copies of
itself, passing 'depth+1' as depth.
Some children are started with the '-k' flag, which will
result in abnormal termination.
*/
int
main (int argc, char *argv[])
{
int n;
n = argc > 1 ? atoi (argv[1]) : 0;
bool is_at_root = (n == 0);
if (is_at_root)
msg ("begin");
/* If -k is passed, crash this process. */
if (argc > 2 && !strcmp(argv[2], "-k"))
{
consume_some_resources_and_die (n);
NOT_REACHED ();
}
int howmany = is_at_root ? EXPECTED_REPETITIONS : 1;
int i, expected_depth = -1;
for (i = 0; i < howmany; i++)
{
pid_t child_pid;
/* Spawn a child that will be abnormally terminated.
To speed the test up, do this only for processes
spawned at a certain depth. */
if (n > EXPECTED_DEPTH_TO_PASS/2)
{
child_pid = spawn_child (n + 1, CRASH);
if (child_pid != -1)
{
if (wait (child_pid) != -1)
fail ("crashed child should return -1.");
}
/* If spawning this child failed, so should
the next spawn_child below. */
}
/* Now spawn the child that will recurse. */
child_pid = spawn_child (n + 1, RECURSE);
/* If maximum depth is reached, return result. */
if (child_pid == -1)
return n;
/* Else wait for child to report how deeply it was able to recurse. */
int reached_depth = wait (child_pid);
if (reached_depth == -1)
fail ("wait returned -1.");
/* Record the depth reached during the first run; on subsequent
runs, fail if those runs do not match the depth achieved on the
first run. */
if (i == 0)
expected_depth = reached_depth;
else if (expected_depth != reached_depth)
fail ("after run %d/%d, expected depth %d, actual depth %d.",
i, howmany, expected_depth, reached_depth);
ASSERT (expected_depth == reached_depth);
}
consume_some_resources ();
if (n == 0)
{
if (expected_depth < EXPECTED_DEPTH_TO_PASS)
fail ("should have forked at least %d times.", EXPECTED_DEPTH_TO_PASS);
msg ("success. program forked %d times.", howmany);
msg ("end");
}
return expected_depth;
}
// vim: sw=2

View File

@@ -0,0 +1,10 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected (IGNORE_USER_FAULTS => 1, IGNORE_EXIT_CODES => 1, [<<'EOF']);
(multi-oom) begin
(multi-oom) success. program forked 10 times.
(multi-oom) end
EOF
pass;

View File

@@ -0,0 +1,8 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF']);
system call!
EOF
pass;

View File

@@ -0,0 +1,13 @@
/* Passes an invalid pointer to the open system call.
The process must be terminated with -1 exit code. */
#include <syscall.h>
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
msg ("open(0x20101234): %d", open ((char *) 0x20101234));
fail ("should have called exit(-1)");
}

View File

@@ -0,0 +1,13 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF', <<'EOF']);
(open-bad-ptr) begin
(open-bad-ptr) end
open-bad-ptr: exit(0)
EOF
(open-bad-ptr) begin
open-bad-ptr: exit(-1)
EOF
pass;

View File

@@ -0,0 +1,14 @@
/* Creates a file whose name spans the boundary between two pages.
This is valid, so it must succeed. */
#include <syscall.h>
#include "tests/userprog/boundary.h"
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
CHECK (open (copy_string_across_boundary ("sample.txt")) > 1,
"open \"sample.txt\"");
}

View File

@@ -0,0 +1,11 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF']);
(open-boundary) begin
(open-boundary) open "sample.txt"
(open-boundary) end
open-boundary: exit(0)
EOF
pass;

View File

@@ -0,0 +1,13 @@
/* Tries to open a file with the empty string as its name. */
#include <syscall.h>
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
int handle = open ("");
if (handle != -1)
fail ("open() returned %d instead of -1", handle);
}

View File

@@ -0,0 +1,10 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF']);
(open-empty) begin
(open-empty) end
open-empty: exit(0)
EOF
pass;

View File

@@ -0,0 +1,13 @@
/* Tries to open a nonexistent file. */
#include <syscall.h>
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
int handle = open ("no-such-file");
if (handle != -1)
fail ("open() returned %d", handle);
}

View File

@@ -0,0 +1,10 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF']);
(open-missing) begin
(open-missing) end
open-missing: exit(0)
EOF
pass;

View File

@@ -0,0 +1,13 @@
/* Open a file. */
#include <syscall.h>
#include "tests/lib.h"
#include "tests/main.h"
void
test_main (void)
{
int handle = open ("sample.txt");
if (handle < 2)
fail ("open() returned %d", handle);
}

View File

@@ -0,0 +1,10 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF']);
(open-normal) begin
(open-normal) end
open-normal: exit(0)
EOF
pass;

View File

@@ -0,0 +1,12 @@
/* Tries to open a file with the null pointer as its name.
The process must be terminated with exit code -1. */
#include <stddef.h>
#include <syscall.h>
#include "tests/main.h"
void
test_main (void)
{
open (NULL);
}

View File

@@ -0,0 +1,13 @@
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF', <<'EOF']);
(open-null) begin
(open-null) end
open-null: exit(0)
EOF
(open-null) begin
open-null: exit(-1)
EOF
pass;

Some files were not shown because too many files have changed in this diff Show More