Add file system persistence tests:
authorBen Pfaff <blp@cs.stanford.edu>
Sat, 27 May 2006 00:06:54 +0000 (00:06 +0000)
committerBen Pfaff <blp@cs.stanford.edu>
Sat, 27 May 2006 00:06:54 +0000 (00:06 +0000)
Change Make.tests to invoke pintos a second time for the extended
filesys tests, and in that run to tar up the file system contents and
copy it out.
Update grading scripts to check the generated tarballs.

Update documentation.

Update documented requirements for remove() of a directory to give
basically the options offered by POSIX, and update the tests to check
for these behaviors.

Remove dir-lsdir test, which no longer made sense given that readdir
is used so heavily in other tests.

Merge dir-mk-vine and dir-rm-vine tests into a single dir-vine test,
which is now much more stringent.

Merge dir-rm-cwd-cd and dir-rm-cwd into a single dir-rm-cwd test,
which is now much more stringent.

Check that a non-empty directory cannot be removed.

Update scoring rubrics.

171 files changed:
TODO
doc/filesys.texi
src/tests/Make.tests
src/tests/filesys/base/lg-create.ck
src/tests/filesys/base/lg-full.ck
src/tests/filesys/base/lg-random.ck
src/tests/filesys/base/lg-seq-block.ck
src/tests/filesys/base/lg-seq-random.ck
src/tests/filesys/base/sm-create.ck
src/tests/filesys/base/sm-full.ck
src/tests/filesys/base/sm-random.ck
src/tests/filesys/base/sm-seq-block.ck
src/tests/filesys/base/sm-seq-random.ck
src/tests/filesys/base/syn-read.ck
src/tests/filesys/base/syn-remove.ck
src/tests/filesys/base/syn-write.ck
src/tests/filesys/extended/Make.tests
src/tests/filesys/extended/Rubric.functionality
src/tests/filesys/extended/Rubric.robustness
src/tests/filesys/extended/dir-empty-name.ck
src/tests/filesys/extended/dir-lsdir.c [deleted file]
src/tests/filesys/extended/dir-lsdir.ck [deleted file]
src/tests/filesys/extended/dir-mk-tree.ck
src/tests/filesys/extended/dir-mk-vine.c [deleted file]
src/tests/filesys/extended/dir-mk-vine.ck [deleted file]
src/tests/filesys/extended/dir-mkdir.ck
src/tests/filesys/extended/dir-open.ck
src/tests/filesys/extended/dir-over-file.ck
src/tests/filesys/extended/dir-rm-cwd-cd.c [deleted file]
src/tests/filesys/extended/dir-rm-cwd-cd.ck [deleted file]
src/tests/filesys/extended/dir-rm-cwd.c
src/tests/filesys/extended/dir-rm-cwd.ck
src/tests/filesys/extended/dir-rm-parent.c
src/tests/filesys/extended/dir-rm-parent.ck
src/tests/filesys/extended/dir-rm-root.c
src/tests/filesys/extended/dir-rm-root.ck
src/tests/filesys/extended/dir-rm-tree.ck
src/tests/filesys/extended/dir-rm-vine.c [deleted file]
src/tests/filesys/extended/dir-rm-vine.ck [deleted file]
src/tests/filesys/extended/dir-rmdir.ck
src/tests/filesys/extended/dir-under-file.ck
src/tests/filesys/extended/dir-vine.c [new file with mode: 0644]
src/tests/filesys/extended/dir-vine.ck [new file with mode: 0644]
src/tests/filesys/extended/grow-create.ck
src/tests/filesys/extended/grow-dir-lg.ck
src/tests/filesys/extended/grow-file-size.ck
src/tests/filesys/extended/grow-root-lg.ck
src/tests/filesys/extended/grow-root-sm.ck
src/tests/filesys/extended/grow-seq-lg.ck
src/tests/filesys/extended/grow-seq-sm.ck
src/tests/filesys/extended/grow-sparse.ck
src/tests/filesys/extended/grow-tell.ck
src/tests/filesys/extended/grow-too-big.c [deleted file]
src/tests/filesys/extended/grow-too-big.ck [deleted file]
src/tests/filesys/extended/grow-two-files.ck
src/tests/filesys/extended/syn-rw.ck
src/tests/filesys/extended/tar.c [new file with mode: 0644]
src/tests/tests.pm
src/tests/threads/alarm-negative.ck
src/tests/threads/alarm-priority.ck
src/tests/threads/alarm-simultaneous.ck
src/tests/threads/alarm-zero.ck
src/tests/threads/alarm.pm
src/tests/threads/mlfqs-block.ck
src/tests/threads/mlfqs-load-1.ck
src/tests/threads/mlfqs-load-60.ck
src/tests/threads/mlfqs-load-avg.ck
src/tests/threads/mlfqs-recent-1.ck
src/tests/threads/mlfqs.pm
src/tests/threads/priority-change.ck
src/tests/threads/priority-condvar.ck
src/tests/threads/priority-donate-lower.ck
src/tests/threads/priority-donate-multiple.ck
src/tests/threads/priority-donate-multiple2.ck
src/tests/threads/priority-donate-nest.ck
src/tests/threads/priority-donate-one.ck
src/tests/threads/priority-donate-sema.ck
src/tests/threads/priority-fifo.ck
src/tests/threads/priority-preempt.ck
src/tests/threads/priority-sema.ck
src/tests/userprog/Make.tests
src/tests/userprog/args-dbl-space.ck
src/tests/userprog/args-many.ck
src/tests/userprog/args-multiple.ck
src/tests/userprog/args-none.ck
src/tests/userprog/args-single.ck
src/tests/userprog/close-bad-fd.ck
src/tests/userprog/close-normal.ck
src/tests/userprog/close-stdin.ck
src/tests/userprog/close-stdout.ck
src/tests/userprog/close-twice.ck
src/tests/userprog/create-bad-ptr.ck
src/tests/userprog/create-bound.ck
src/tests/userprog/create-empty.ck
src/tests/userprog/create-exists.ck
src/tests/userprog/create-long.ck
src/tests/userprog/create-normal.ck
src/tests/userprog/create-null.ck
src/tests/userprog/exec-arg.ck
src/tests/userprog/exec-bad-ptr.ck
src/tests/userprog/exec-missing.ck
src/tests/userprog/exec-multiple.ck
src/tests/userprog/exec-once.ck
src/tests/userprog/exit.ck
src/tests/userprog/halt.ck
src/tests/userprog/multi-child-fd.ck
src/tests/userprog/multi-recurse.ck
src/tests/userprog/no-vm/multi-oom.ck
src/tests/userprog/null.ck
src/tests/userprog/open-bad-ptr.ck
src/tests/userprog/open-boundary.ck
src/tests/userprog/open-empty.ck
src/tests/userprog/open-missing.ck
src/tests/userprog/open-normal.ck
src/tests/userprog/open-null.ck
src/tests/userprog/open-twice.ck
src/tests/userprog/read-bad-fd.ck
src/tests/userprog/read-bad-ptr.ck
src/tests/userprog/read-boundary.ck
src/tests/userprog/read-normal.ck
src/tests/userprog/read-stdout.ck
src/tests/userprog/read-zero.ck
src/tests/userprog/rox-child.ck
src/tests/userprog/rox-multichild.ck
src/tests/userprog/rox-simple.ck
src/tests/userprog/sc-bad-arg.ck
src/tests/userprog/sc-bad-sp.ck
src/tests/userprog/sc-boundary-2.ck
src/tests/userprog/sc-boundary.ck
src/tests/userprog/wait-bad-pid.ck
src/tests/userprog/wait-killed.ck
src/tests/userprog/wait-simple.ck
src/tests/userprog/wait-twice.ck
src/tests/userprog/write-bad-fd.ck
src/tests/userprog/write-bad-ptr.ck
src/tests/userprog/write-boundary.ck
src/tests/userprog/write-normal.ck
src/tests/userprog/write-stdin.ck
src/tests/userprog/write-zero.ck
src/tests/vm/Make.tests
src/tests/vm/mmap-bad-fd.ck
src/tests/vm/mmap-clean.ck
src/tests/vm/mmap-close.ck
src/tests/vm/mmap-exit.ck
src/tests/vm/mmap-inherit.ck
src/tests/vm/mmap-misalign.ck
src/tests/vm/mmap-null.ck
src/tests/vm/mmap-over-code.ck
src/tests/vm/mmap-over-data.ck
src/tests/vm/mmap-over-stk.ck
src/tests/vm/mmap-overlap.ck
src/tests/vm/mmap-read.ck
src/tests/vm/mmap-remove.ck
src/tests/vm/mmap-shuffle.ck
src/tests/vm/mmap-twice.ck
src/tests/vm/mmap-write.ck
src/tests/vm/mmap-zero.ck
src/tests/vm/page-linear.ck
src/tests/vm/page-merge-par.ck
src/tests/vm/page-merge-seq.ck
src/tests/vm/page-parallel.ck
src/tests/vm/page-shuffle.ck
src/tests/vm/process_death.pm
src/tests/vm/pt-bad-read.ck
src/tests/vm/pt-big-stk-obj.ck
src/tests/vm/pt-grow-bad.ck
src/tests/vm/pt-grow-pusha.ck
src/tests/vm/pt-grow-stack.ck
src/tests/vm/pt-grow-stk-sc.ck
src/tests/vm/pt-write-code2.ck
tests/Makefile

diff --git a/TODO b/TODO
index 68837f72baf077017f8525c7ed3bb621f8f83edc..463cb88457023fa1ab82af25120f68cbc3dfbc48 100644 (file)
--- a/TODO
+++ b/TODO
 
     (Perhaps we should count disk reads and writes, not time.)
 
-  - Do we check that non-empty directories cannot be removed?
-
   - Need lots more tests.
 
-  - Add FS persistence test(s).
-
   - Detect implementations that represent the cwd as a string, by
     removing a directory that is the cwd of another process, then
     creating a new directory of the same name and putting some files
     in it, then checking whether the process that had it as cwd sees
     them.
 
+  - dir-rm-cwd should have a related test that uses a separate process
+    to try to pin the directory as its cwd.
+
   - Godmar: I'm not sure if I mentioned that already, but I passed all
     tests for the filesys project without having implemented inode
     deallocation. A test is needed that checks that blocks are
index a93481cca37da657cf8ec50890691e12f2d39dfe..db4d94810b63426f91ee03c6783bd63b5c1060be 100644 (file)
@@ -25,6 +25,7 @@ to 5% extra credit if you do enable VM.
 
 @menu
 * File System New Code::        
+* Testing File System Persistence::  
 @end menu
 
 @node File System New Code
@@ -78,6 +79,35 @@ which you will remove.
 While most of your work will be in @file{filesys}, you should be
 prepared for interactions with all previous parts.
 
+@node Testing File System Persistence
+@subsection Testing File System Persistence
+
+By now, you should be familiar with the basic process of running the
+Pintos tests.  @xref{Testing}, for review, if necessary.
+
+Until now, each test invoked Pintos just once.  However, an important
+purpose of a file system is to ensure that data remains accessible from
+one boot to another.  Thus, the tests that are part of the file system
+project invoke Pintos a second time.  The second run combines all the
+files and directories in the file system into a single file, then copies
+that file out of the Pintos file system into the host (Unix) file
+system.
+
+The grading scripts check the file system's correctness based on the
+contents of the file copied out in the second run.  This means that your
+project will not pass any of the extended file system tests until the
+file system is implemented well enough to support @program{tar}, the
+Pintos user program that produces the file that is copied out.  The
+@program{tar} program is fairly demanding (it requires both extensible
+file and subdirectory support), so this will take some work.  Until
+then, you can ignore errors from @command{make check} regarding the
+extracted file system.
+
+Incidentally, as you may have surmised, the file format used for copying
+out the file system contents is the standard Unix ``tar'' format.  You
+can use the Unix @command{tar} program to examine them.  The tar file
+for test @var{t} is named @file{@var{t}.tar}.
+
 @node Project 4 Requirements
 @section Requirements
 
@@ -175,15 +205,19 @@ The directory separator character is forward slash (@samp{/}).
 You must also support special file names @file{.} and @file{..}, which
 have the same meanings as they do in Unix.
 
-Update the @code{remove} system call so that it can delete empty
-directories in addition to regular files.  Directories may only be
-deleted if they do not contain any files or subdirectories (other than
-@file{.} and @file{..}).
-
 Update the @code{open} system call so that it can also open directories.
 Of the existing system calls, only @code{close} needs to accept a file
 descriptor for a directory.
 
+Update the @code{remove} system call so that it can delete empty
+directories (other than the root) in addition to regular files.
+Directories may only be deleted if they do not contain any files or
+subdirectories (other than @file{.} and @file{..}).  You may decide
+whether to allow deletion of a directory that is open by a process or in
+use as a process's current working directory.  If it is allowed, then
+attempts to open files (including @file{.} and @file{..}) or create new
+files in a deleted directory must be disallowed.
+
 Implement the following new system calls:
 
 @deftypefn {System Call} bool chdir (const char *@var{dir})
index 9cb992bda4b48b8b288f7d877e4142d0ea536336..b98a75d33e65d460a565373d7682865551c7b448 100644 (file)
@@ -5,19 +5,16 @@ include $(patsubst %,$(SRCDIR)/%/Make.tests,$(TEST_SUBDIRS))
 PROGS = $(foreach subdir,$(TEST_SUBDIRS),$($(subdir)_PROGS))
 TESTS = $(foreach subdir,$(TEST_SUBDIRS),$($(subdir)_TESTS))
 
-include ../../Makefile.userprog
-
-TIMEOUT = 60
-PINTOSFLAGS += -v -T $(TIMEOUT)                                                \
-       $(foreach file,$(PUTFILES),-p $(file) -a $(notdir $(file)))
-KERNELFLAGS += -q
-
-PINTOS = pintos $(SIMULATOR) $(PINTOSOPTS) $(PINTOSFLAGS) -- $(KERNELFLAGS)
-
 OUTPUTS = $(addsuffix .output,$(TESTS))
 ERRORS = $(addsuffix .errors,$(TESTS))
 RESULTS = $(addsuffix .result,$(TESTS))
 
+ifdef PROGS
+include ../../Makefile.userprog
+endif
+
+TIMEOUT = 60
+
 clean::
        rm -f $(OUTPUTS) $(ERRORS) $(RESULTS) 
 
@@ -48,11 +45,27 @@ outputs:: $(OUTPUTS)
 
 $(foreach prog,$(PROGS),$(eval $(prog).output: $(prog)))
 $(foreach test,$(TESTS),$(eval $(test).output: $($(test)_PUTFILES)))
-tests/%.output: RUNCMD = $(if $($*_ARGS),run '$(*F) $($*_ARGS)',run $(*F))
-tests/%.output: RUNREDIR = 2>$*.errors $(if $(VERBOSE),|tee,>) $*.output
-tests/%.output: RUNTEST = $(PINTOS) $(RUNCMD) $(RUNREDIR)
+$(foreach test,$(TESTS),$(eval $(test).output: TEST = $(test)))
+
+TESTCMD = pintos -v -T $(TIMEOUT)
+TESTCMD += $(SIMULATOR)
+TESTCMD += $(PINTOSOPTS)
+ifeq ($(filter userprog, $(KERNEL_SUBDIRS)), userprog)
+TESTCMD += --fs-disk=$(FSDISK)
+TESTCMD += $(foreach file,$(PUTFILES),-p $(file) -a $(notdir $(file)))
+endif
+ifeq ($(filter vm, $(KERNEL_SUBDIRS)), vm)
+TESTCMD += --swap-disk=4
+endif
+TESTCMD += -- -q 
+TESTCMD += $(KERNELFLAGS)
+ifeq ($(filter userprog, $(KERNEL_SUBDIRS)), userprog)
+TESTCMD += -f
+endif
+TESTCMD += $(if $($(TEST)_ARGS),run '$(*F) $($(TEST)_ARGS)',run $(*F))
+TESTCMD += 2> $(TEST).errors $(if $(VERBOSE),|tee,>) $(TEST).output
 %.output: os.dsk
-       $(RUNTEST)
+       $(TESTCMD)
 
 %.result: %.ck %.output
        perl -I$(SRCDIR) $< $* $@
index 10f30974e76ba4c09992506d81388a81e3839f9e..86b2c513b778a0176c10eca37f44ec08112d3afd 100644 (file)
@@ -10,3 +10,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (lg-create) close "blargle"
 (lg-create) end
 EOF
+pass;
index a38059403139ed2a85621989d35ad8147cb82dfe..ee6c7f9e66ed5204a0937d9630d21250880abf4d 100644 (file)
@@ -13,3 +13,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (lg-full) close "quux"
 (lg-full) end
 EOF
+pass;
index 4d6d752a9303de32e398812105a7cd025a8107d9..dd9f1dd0f590ed6ca95181cb327e6f4a85333ac7 100644 (file)
@@ -11,3 +11,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (lg-random) close "bazzle"
 (lg-random) end
 EOF
+pass;
index 8c979c70c46b8b47c9e85de141d5d8270c25402f..b78908119e73409581dd3161976a94ee50e9712f 100644 (file)
@@ -13,3 +13,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (lg-seq-block) close "noodle"
 (lg-seq-block) end
 EOF
+pass;
index 56fd9984ad26ee4773ad69bbc948e5522ae5c802..6b2dc82a199faa93df8e627fce9981ef31b5bb49 100644 (file)
@@ -13,3 +13,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (lg-seq-random) close "nibble"
 (lg-seq-random) end
 EOF
+pass;
index d4a63173de6b8557cc51e016531689a3e1380566..8ca80dc30d5bd3cf051cfd5b794c0e5a80f3a77b 100644 (file)
@@ -10,3 +10,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (sm-create) close "blargle"
 (sm-create) end
 EOF
+pass;
index 6fa480579bf136cf9226e192767aba04b6afb950..2e0eb3676b3ac1961d17acabb4daa3fdc5ba8505 100644 (file)
@@ -13,3 +13,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (sm-full) close "quux"
 (sm-full) end
 EOF
+pass;
index 29b2fb7defd5639aea37f85a77fbadc022db3d50..bda049de53e88a83ee7ea8a1cea2883ec1e2e57b 100644 (file)
@@ -11,3 +11,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (sm-random) close "bazzle"
 (sm-random) end
 EOF
+pass;
index 15566682924646fb9e45f6f5f68016da29693f77..0e2939d81d1deffb48e81603b184f5a265bd1e9d 100644 (file)
@@ -13,3 +13,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (sm-seq-block) close "noodle"
 (sm-seq-block) end
 EOF
+pass;
index 47f9d88fb9dcca5976f7fd48ce099e301785468a..2fb368bcca5e8ec7392a3c7be9759758b256f171 100644 (file)
@@ -13,3 +13,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (sm-seq-random) close "nibble"
 (sm-seq-random) end
 EOF
+pass;
index 7bda1aabf1fad089a6ea16b5526ceb5a4c6832b2..e2f68e80a2fe142fc6fbd039d9bddb7e1f890784 100644 (file)
@@ -30,3 +30,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (syn-read) wait for child 10 of 10 returned 9 (expected 9)
 (syn-read) end
 EOF
+pass;
index 79a5cb7a9bf6ebaa1f2a55fd094f375e1977e4e3..16ff11e550451ec5e4041d4bf82d1a5367cfcbfe 100644 (file)
@@ -13,3 +13,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (syn-remove) close "deleteme"
 (syn-remove) end
 EOF
+pass;
index da52dd88bc6b5b7eef73f329401f019e82f1dc14..629a7a2b793486577ce04e0e55733b2d967a1434 100644 (file)
@@ -29,3 +29,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (syn-write) read "stuff"
 (syn-write) end
 EOF
+pass;
index 9f03c6e3a6820fd5941af0900c2efa388cecb2e9..1aeb8dd1acb68ba0071d6580b1b38f3d88662fd1 100644 (file)
@@ -1,21 +1,49 @@
 # -*- makefile -*-
 
 tests/filesys/extended_TESTS = $(addprefix                             \
-tests/filesys/extended/,dir-empty-name dir-lsdir dir-mk-tree           \
-dir-mk-vine dir-mkdir dir-open dir-over-file dir-rm-cwd-cd dir-rm-cwd  \
-dir-rm-parent dir-rm-root dir-rm-tree dir-rm-vine dir-rmdir            \
-dir-under-file grow-create grow-dir-lg grow-file-size grow-root-lg     \
-grow-root-sm grow-seq-lg grow-seq-sm grow-sparse grow-tell             \
-grow-too-big grow-two-files syn-rw)
+tests/filesys/extended/,dir-empty-name dir-mk-tree dir-mkdir dir-open  \
+dir-over-file dir-rm-cwd dir-rm-parent dir-rm-root dir-rm-tree         \
+dir-rmdir dir-under-file dir-vine grow-create grow-dir-lg              \
+grow-file-size grow-root-lg grow-root-sm grow-seq-lg grow-seq-sm       \
+grow-sparse grow-tell grow-two-files syn-rw)
 
 tests/filesys/extended_PROGS = $(tests/filesys/extended_TESTS) \
-tests/filesys/extended/child-syn-rw
+tests/filesys/extended/child-syn-rw tests/filesys/extended/tar
 
 $(foreach prog,$(tests/filesys/extended_PROGS),                        \
        $(eval $(prog)_SRC += $(prog).c tests/lib.c tests/filesys/seq-test.c))
 $(foreach prog,$(tests/filesys/extended_TESTS),                \
        $(eval $(prog)_SRC += tests/main.c))
+$(foreach prog,$(tests/filesys/extended_TESTS),                \
+       $(eval $(prog)_PUTFILES += tests/filesys/extended/tar))
+$(foreach test,$(tests/filesys/extended_TESTS),        \
+       $(eval $(test).output: FSDISK = tmp.dsk))
+
 tests/filesys/extended/dir-mk-tree_SRC += tests/filesys/extended/mk-tree.c
 tests/filesys/extended/dir-rm-tree_SRC += tests/filesys/extended/mk-tree.c
 
-tests/filesys/extended/syn-rw_PUTFILES = tests/filesys/extended/child-syn-rw
+tests/filesys/extended/syn-rw_PUTFILES += tests/filesys/extended/child-syn-rw
+
+
+GETTIMEOUT = 60
+
+GETCMD = pintos -v -T $(GETTIMEOUT)
+GETCMD += $(PINTOSOPTS)
+GETCMD += $(SIMULATOR)
+GETCMD += --fs-disk=$(FSDISK)
+GETCMD += -g fs.tar -a $(TEST).tar
+ifeq ($(filter vm, $(KERNEL_SUBDIRS)), vm)
+GETCMD += --swap-disk=4
+endif
+GETCMD += -- -q
+GETCMD += $(KERNELFLAGS)
+GETCMD += run 'tar fs.tar /'
+GETCMD += 2>> $(TEST).get-errors
+GETCMD += $(if $(VERBOSE),|tee -a,>>) $(TEST).get-output
+
+tests/filesys/extended/%.output: os.dsk
+       rm -f tmp.dsk
+       pintos-mkdisk tmp.dsk 2
+       $(TESTCMD)
+       $(GETCMD)
+       rm -f tmp.dsk
index 0e36889e638ce81710e2aa99cc19dd21f5c9a074..94f7c2ce1e66afbd023a14e5258bb1b95265e57b 100644 (file)
@@ -1,14 +1,12 @@
 Functionality of extended file system:
 - Test directory support.
 1      dir-mkdir
-2      dir-mk-vine
 3      dir-mk-tree
 
 1      dir-rmdir
-2      dir-rm-vine
 3      dir-rm-tree
 
-1      dir-lsdir
+5      dir-vine
 
 - Test file growth.
 1      grow-create
index 2f58ca8781319f30cbc6a4e8abfa50b691181187..fb9f32fe2cd7880b0a8304f0e6fe0e9a19f5c2db 100644 (file)
@@ -4,9 +4,6 @@ Robustness of file system:
 1      dir-over-file
 1      dir-under-file
 
-1      dir-rm-cwd
-2      dir-rm-cwd-cd
+3      dir-rm-cwd
 2      dir-rm-parent
 1      dir-rm-root
-
-1      grow-too-big
index c2d87f876b93bd47836e2a0dc0fd65f48162cae3..c4cbc6bece91591929dd25c2a9878ebd3b907cf7 100644 (file)
@@ -7,3 +7,5 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (dir-empty-name) create "" (must return false)
 (dir-empty-name) end
 EOF
+check_archive ({});
+pass;
diff --git a/src/tests/filesys/extended/dir-lsdir.c b/src/tests/filesys/extended/dir-lsdir.c
deleted file mode 100644 (file)
index 254e595..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/* Lists the contents of a directory using readdir. */
-
-#include <syscall.h>
-#include "tests/lib.h"
-#include "tests/main.h"
-
-void
-test_main (void) 
-{
-  int fd;
-  char name[READDIR_MAX_LEN + 1];
-
-  CHECK ((fd = open (".")) > 1, "open .");
-  CHECK (isdir (fd), "isdir(.)");
-
-  while (readdir (fd, name))
-    msg ("readdir: \"%s\"", name);
-
-  msg ("close .");
-  close (fd);
-}
diff --git a/src/tests/filesys/extended/dir-lsdir.ck b/src/tests/filesys/extended/dir-lsdir.ck
deleted file mode 100644 (file)
index 36a4e52..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-# -*- perl -*-
-use strict;
-use warnings;
-use tests::tests;
-
-our ($test);
-my (@output) = read_text_file ("$test.output");
-
-common_checks (@output);
-@output = get_core_output (@output);
-
-must_contain_in_order (\@output,
-                      '(dir-lsdir) open .',
-                      '(dir-lsdir) isdir(.)',
-                      '(dir-lsdir) close .');
-
-sub must_contain_in_order {
-    my ($output, @lines) = @_;
-    my (@line_numbers) = map (find_line ($_, @$output), @lines);
-    for my $i (0...$#lines - 1) {
-       fail "\"$lines[$i]\" follows \"$lines[$i + 1]\" in output\n"
-         if $line_numbers[$i] > $line_numbers[$i + 1];
-    }
-}
-
-sub find_line {
-    my ($line, @output) = @_;
-    for my $i (0...$#output) {
-       return $i if $line eq $output[$i];
-    }
-    fail "\"$line\" does not appear in output\n";
-}
-
-my (%count);
-for my $fn (map (/readdir: \"([^"]+)\"/, @output)) {
-    fail "Unexpected file \"$fn\" in lsdir output\n"
-      unless grep ($_ eq $fn, qw (dir-lsdir));
-    fail "File \"$fn\" listed twice in lsdir output\n"
-      if $count{$fn};
-    $count{$fn}++;
-}
-fail "No files in lsdir output\n" if scalar (keys (%count)) == 0;
-fail "File \"dir-lsdir\" missing from lsdir output\n"
-  if !$count{"dir-lsdir"};
-
-pass;
index 8d771456ff96ad051ffc0e97d340d35959b2d040..046e50941827714f8c1266d15f62b7e030d444ad 100644 (file)
@@ -9,3 +9,15 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (dir-mk-tree) close "/0/2/0/3"
 (dir-mk-tree) end
 EOF
+my ($tree);
+for my $a (0...3) {
+    for my $b (0...2) {
+       for my $c (0...2) {
+           for my $d (0...3) {
+               $tree->{$a}{$b}{$c}{$d} = [''];
+           }
+       }
+    }
+}
+check_archive ($tree);
+pass;
diff --git a/src/tests/filesys/extended/dir-mk-vine.c b/src/tests/filesys/extended/dir-mk-vine.c
deleted file mode 100644 (file)
index 444727a..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Creates a "vine" of directories /0/1/2/3/4/5/6/7/8/9
-   and changes directory into each of them,
-   then creates a test file in the bottommost
-   and verifies that it can be opened by absolute name. */
-
-#include <syscall.h>
-#include "tests/lib.h"
-#include "tests/main.h"
-
-void
-test_main (void) 
-{
-  const char *file_name = "/0/1/2/3/4/5/6/7/8/9/test";
-  char dir[2];
-  
-  dir[1] = '\0';
-  for (dir[0] = '0'; dir[0] <= '9'; dir[0]++) 
-    {
-      CHECK (mkdir (dir), "mkdir \"%s\"", dir);
-      CHECK (chdir (dir), "chdir \"%s\"", dir);
-    }
-  CHECK (create ("test", 512), "create \"test\"");
-  CHECK (chdir ("/"), "chdir \"/\"");
-  CHECK (open (file_name) > 1, "open \"%s\"", file_name);
-}
-
diff --git a/src/tests/filesys/extended/dir-mk-vine.ck b/src/tests/filesys/extended/dir-mk-vine.ck
deleted file mode 100644 (file)
index 1f9db74..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-# -*- perl -*-
-use strict;
-use warnings;
-use tests::tests;
-check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
-(dir-mk-vine) begin
-(dir-mk-vine) mkdir "0"
-(dir-mk-vine) chdir "0"
-(dir-mk-vine) mkdir "1"
-(dir-mk-vine) chdir "1"
-(dir-mk-vine) mkdir "2"
-(dir-mk-vine) chdir "2"
-(dir-mk-vine) mkdir "3"
-(dir-mk-vine) chdir "3"
-(dir-mk-vine) mkdir "4"
-(dir-mk-vine) chdir "4"
-(dir-mk-vine) mkdir "5"
-(dir-mk-vine) chdir "5"
-(dir-mk-vine) mkdir "6"
-(dir-mk-vine) chdir "6"
-(dir-mk-vine) mkdir "7"
-(dir-mk-vine) chdir "7"
-(dir-mk-vine) mkdir "8"
-(dir-mk-vine) chdir "8"
-(dir-mk-vine) mkdir "9"
-(dir-mk-vine) chdir "9"
-(dir-mk-vine) create "test"
-(dir-mk-vine) chdir "/"
-(dir-mk-vine) open "/0/1/2/3/4/5/6/7/8/9/test"
-(dir-mk-vine) end
-EOF
index d4e062b30b5c911ce6e390a8a9a87c83d3a65613..7cde055dd5d1778e8f29916c1c3759ba1c241e1d 100644 (file)
@@ -10,3 +10,5 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (dir-mkdir) open "b"
 (dir-mkdir) end
 EOF
+check_archive ({'a' => {'b' => ["\0" x 512]}});
+pass;
index e16e9a0285b4398d43366761bf83e73a8234487b..01eccbafa22f241a10bfd83b8a3133e83e2047a2 100644 (file)
@@ -17,3 +17,5 @@ EOF
 (dir-open) write "xyzzy"
 dir-open: exit(-1)
 EOF
+check_archive ({"xyzzy" => {}});
+pass;
index 208fd9f5e34b5b44f1cd2b3bbfaac36be218c2a1..52084292a698a589a3bf6c6f3ecc7ec9f4fd769d 100644 (file)
@@ -8,3 +8,5 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (dir-over-file) create "abc" (must return false)
 (dir-over-file) end
 EOF
+check_archive ({"abc" => {}});
+pass;
diff --git a/src/tests/filesys/extended/dir-rm-cwd-cd.c b/src/tests/filesys/extended/dir-rm-cwd-cd.c
deleted file mode 100644 (file)
index c9a6e61..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Tries to remove the current directory.
-   This is allowed to succeed or fail.
-   If it succeeds, then it must not be possible to chdir back to
-   the current directory by name (because it's been deleted).
-   If it fails, then it must be possible to chdir back to the
-   current directory by name (because it still exists). */
-
-#include <syscall.h>
-#include "tests/lib.h"
-#include "tests/main.h"
-
-void
-test_main (void) 
-{
-  CHECK (mkdir ("a"), "mkdir \"a\"");
-  CHECK (chdir ("a"), "chdir \"a\"");
-  msg ("remove \"/a\" (must not crash)");
-  if (remove ("/a"))
-    CHECK (!chdir ("/a"),
-           "chdir \"/a\" (remove succeeded so this must return false)");
-  else
-    CHECK (chdir ("/a"), "chdir \"/a\" (remove failed so this must succeed)");
-}
diff --git a/src/tests/filesys/extended/dir-rm-cwd-cd.ck b/src/tests/filesys/extended/dir-rm-cwd-cd.ck
deleted file mode 100644 (file)
index fc49668..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- perl -*-
-use strict;
-use warnings;
-use tests::tests;
-check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF', <<'EOF']);
-(dir-rm-cwd-cd) begin
-(dir-rm-cwd-cd) mkdir "a"
-(dir-rm-cwd-cd) chdir "a"
-(dir-rm-cwd-cd) remove "/a" (must not crash)
-(dir-rm-cwd-cd) chdir "/a" (remove succeeded so this must return false)
-(dir-rm-cwd-cd) end
-EOF
-(dir-rm-cwd-cd) begin
-(dir-rm-cwd-cd) mkdir "a"
-(dir-rm-cwd-cd) chdir "a"
-(dir-rm-cwd-cd) remove "/a" (must not crash)
-(dir-rm-cwd-cd) chdir "/a" (remove failed so this must succeed)
-(dir-rm-cwd-cd) end
-EOF
index 7f81a0bef234c5e18030fda20dd0f34b77309f54..78e13dea23492dd5f69953220c53d25b898f2b95 100644 (file)
@@ -1,19 +1,75 @@
-/* Tries to remove the current directory.
-   This is allowed to succeed or fail.
-   Then creates a file in the root to make sure that we haven't
-   corrupted any directory state. */
+/* Tries to remove the current directory, which may succeed or
+   fail.  The requirements in each case are different; refer to
+   the assignment for details. */
 
 #include <syscall.h>
 #include "tests/lib.h"
 #include "tests/main.h"
 
+static int
+wrap_open (const char *name) 
+{
+  static int fds[8], fd_cnt;
+  int fd, i;
+
+  CHECK ((fd = open (name)) > 1, "open \"%s\"", name);
+  for (i = 0; i < fd_cnt; i++)
+    if (fds[i] == fd)
+      fail ("fd returned is not unique");
+  fds[fd_cnt++] = fd;
+  return fd;
+}
+
 void
 test_main (void) 
 {
+  int root_fd, a_fd0;
+  char name[READDIR_MAX_LEN + 1];
+
+  root_fd = wrap_open ("/");
   CHECK (mkdir ("a"), "mkdir \"a\"");
+
+  a_fd0 = wrap_open ("/a");
+  CHECK (!readdir (a_fd0, name), "verify \"/a\" is empty");
+  CHECK (inumber (root_fd) != inumber (a_fd0),
+         "\"/\" and \"/a\" must have different inumbers");
+
   CHECK (chdir ("a"), "chdir \"a\"");
-  msg ("remove \"/a\" (must not crash)");
-  remove ("/a");
-  msg ("create \"b\" (must not crash)");
-  create ("b", 123);
+
+  msg ("try to remove \"/a\"");
+  if (remove ("/a"))
+    {
+      msg ("remove successful");
+
+      CHECK (open ("/a") == -1, "open \"/a\" (must fail)");
+      CHECK (open (".") == -1, "open \".\" (must fail)");
+      CHECK (open ("..") == -1, "open \"..\" (must fail)");
+      CHECK (!create ("x", 512), "create \"x\" (must fail)");
+    }
+  else
+    {
+      int a_fd1, a_fd2, a_fd3;
+
+      msg ("remove failed");
+
+      CHECK (!remove ("../a"), "try to remove \"../a\" (must fail)");
+      CHECK (!remove (".././a"), "try to remove \".././a\" (must fail)");
+      CHECK (!remove ("/./a"), "try to remove \"/./a\" (must fail)");
+
+      a_fd1 = wrap_open ("/a");
+      a_fd2 = wrap_open (".");
+      CHECK (inumber (a_fd1) == inumber (a_fd2),
+             "\"/a\" and \".\" must have same inumber");
+      CHECK (inumber (root_fd) != inumber (a_fd1),
+             "\"/\" and \"/a\" must have different inumbers");
+
+      CHECK (chdir ("/a"), "chdir \"/a\"");
+      a_fd3 = wrap_open (".");
+      CHECK (inumber (a_fd3) == inumber (a_fd1),
+             "\".\" must have same inumber as before");
+
+      CHECK (chdir ("/"), "chdir \"/\"");
+      CHECK (!remove ("a"), "try to remove \"a\" (must fail: still open)");
+    }
+  CHECK (!readdir (a_fd0, name), "verify \"/a\" is empty");
 }
index 91e7c0f37074741b6f122f7a7b551aac9f34d0be..8821f0d767c24f43f671220eedf9dea5fc23933c 100644 (file)
@@ -2,11 +2,48 @@
 use strict;
 use warnings;
 use tests::tests;
-check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
+my ($cwd_removable) = check_expected (IGNORE_EXIT_CODES => 1,
+                                     {NO => <<'EOF', YES => <<'EOF'});
 (dir-rm-cwd) begin
+(dir-rm-cwd) open "/"
 (dir-rm-cwd) mkdir "a"
+(dir-rm-cwd) open "/a"
+(dir-rm-cwd) verify "/a" is empty
+(dir-rm-cwd) "/" and "/a" must have different inumbers
 (dir-rm-cwd) chdir "a"
-(dir-rm-cwd) remove "/a" (must not crash)
-(dir-rm-cwd) create "b" (must not crash)
+(dir-rm-cwd) try to remove "/a"
+(dir-rm-cwd) remove failed
+(dir-rm-cwd) try to remove "../a" (must fail)
+(dir-rm-cwd) try to remove ".././a" (must fail)
+(dir-rm-cwd) try to remove "/./a" (must fail)
+(dir-rm-cwd) open "/a"
+(dir-rm-cwd) open "."
+(dir-rm-cwd) "/a" and "." must have same inumber
+(dir-rm-cwd) "/" and "/a" must have different inumbers
+(dir-rm-cwd) chdir "/a"
+(dir-rm-cwd) open "."
+(dir-rm-cwd) "." must have same inumber as before
+(dir-rm-cwd) chdir "/"
+(dir-rm-cwd) try to remove "a" (must fail: still open)
+(dir-rm-cwd) verify "/a" is empty
 (dir-rm-cwd) end
 EOF
+(dir-rm-cwd) begin
+(dir-rm-cwd) open "/"
+(dir-rm-cwd) mkdir "a"
+(dir-rm-cwd) open "/a"
+(dir-rm-cwd) verify "/a" is empty
+(dir-rm-cwd) "/" and "/a" must have different inumbers
+(dir-rm-cwd) chdir "a"
+(dir-rm-cwd) try to remove "/a"
+(dir-rm-cwd) remove successful
+(dir-rm-cwd) open "/a" (must fail)
+(dir-rm-cwd) open "." (must fail)
+(dir-rm-cwd) open ".." (must fail)
+(dir-rm-cwd) create "x" (must fail)
+(dir-rm-cwd) verify "/a" is empty
+(dir-rm-cwd) end
+EOF
+  
+check_archive ($cwd_removable eq 'YES' ? {} : {"a" => {}});
+pass;
index 78e84b1c76b48613947ecc23fc4e4c3b9f120a29..eb43f5b6cf6070b9767bafa315165ffc3afa8786 100644 (file)
@@ -1,6 +1,5 @@
-/* Tries to remove the change of parents of the current
-   directory.
-   This can succeed or fail as long as it doesn't crash. */
+/* Tries to remove a parent of the current directory.  This must
+   fail, because that directory is non-empty. */
 
 #include <syscall.h>
 #include "tests/lib.h"
@@ -13,8 +12,5 @@ test_main (void)
   CHECK (chdir ("a"), "chdir \"a\"");
   CHECK (mkdir ("b"), "mkdir \"b\"");
   CHECK (chdir ("b"), "chdir \"b\"");
-  msg ("remove \"/b\" (must not crash)");
-  remove ("/b");
-  msg ("remove \"/a\" (must not crash)");
-  remove ("/a");
+  CHECK (!remove ("/a"), "remove \"/a\" (must fail)");
 }
index 92301a5f926dde1e04f216fa4d9e7492138a9bc6..acbacc12db155a1d2bfdc07b732b9cc5cb651b45 100644 (file)
@@ -8,7 +8,8 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (dir-rm-parent) chdir "a"
 (dir-rm-parent) mkdir "b"
 (dir-rm-parent) chdir "b"
-(dir-rm-parent) remove "/b" (must not crash)
-(dir-rm-parent) remove "/a" (must not crash)
+(dir-rm-parent) remove "/a" (must fail)
 (dir-rm-parent) end
 EOF
+check_archive ({"a" => {"b" => {}}});
+pass;
index 5f9cb61509da6c04867e7246342e95c3f918a69e..c47f1eb7b47f6c135c80291a1ec5ebee4e7fd52f 100644 (file)
@@ -1,5 +1,5 @@
 /* Try to remove the root directory.
-   This must return failure. */
+   This must fail. */
 
 #include <syscall.h>
 #include "tests/lib.h"
@@ -8,6 +8,6 @@
 void
 test_main (void) 
 {
-  CHECK (!remove ("/"), "remove \"/\" (must return false)");
+  CHECK (!remove ("/"), "remove \"/\" (must fail)");
   CHECK (create ("/a", 243), "create \"/a\"");
 }
index 38894dded793c913d4d639c559a383fd2ddb3216..b203cc6394aaa1758814f2b36c12e6cf787c9664 100644 (file)
@@ -4,7 +4,9 @@ use warnings;
 use tests::tests;
 check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (dir-rm-root) begin
-(dir-rm-root) remove "/" (must return false)
+(dir-rm-root) remove "/" (must fail)
 (dir-rm-root) create "/a"
 (dir-rm-root) end
 EOF
+check_archive ({"a" => ["\0" x 243]});
+pass;
index 519eff007f0da6e237272ec129fce5ffae75395b..7e3ae6e1f46b84233c25131294c4908c6cb7a52f 100644 (file)
@@ -11,3 +11,5 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (dir-rm-tree) open "/3/0/2/0" (must return -1)
 (dir-rm-tree) end
 EOF
+check_archive ({});
+pass;
diff --git a/src/tests/filesys/extended/dir-rm-vine.c b/src/tests/filesys/extended/dir-rm-vine.c
deleted file mode 100644 (file)
index e01ff49..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Creates a "vine" of directories /0/1/2/3/4/5/6/7/8/9
-   and changes directory into each of them,
-   then remove them. */
-
-#include <string.h>
-#include <syscall.h>
-#include "tests/lib.h"
-#include "tests/main.h"
-
-void
-test_main (void) 
-{
-  const char *file_name = "/0/1/2/3/4/5/6/7/8/9/test";
-  int fd;
-  char tmp[128];
-  
-  tmp[1] = '\0';
-  for (tmp[0] = '0'; tmp[0] <= '9'; tmp[0]++) 
-    {
-      CHECK (mkdir (tmp), "mkdir \"%s\"", tmp);
-      CHECK (chdir (tmp), "chdir \"%s\"", tmp);
-    }
-  CHECK (create ("test", 512), "create \"test\"");
-
-  CHECK (chdir ("/"), "chdir \"/\"");
-  CHECK ((fd = open (file_name)) > 1, "open \"%s\"", file_name);
-  msg ("close \"%s\"", file_name);
-  close (fd);
-
-  strlcpy (tmp, file_name, sizeof tmp);
-  while (strlen (tmp) > 0)
-    {
-      CHECK (remove (tmp), "remove \"%s\"", tmp);
-      *strrchr (tmp, '/') = 0;
-    }
-
-  CHECK (open (file_name) == -1, "open \"%s\" (must return -1)", file_name);
-}
diff --git a/src/tests/filesys/extended/dir-rm-vine.ck b/src/tests/filesys/extended/dir-rm-vine.ck
deleted file mode 100644 (file)
index d8e3638..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-# -*- perl -*-
-use strict;
-use warnings;
-use tests::tests;
-check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
-(dir-rm-vine) begin
-(dir-rm-vine) mkdir "0"
-(dir-rm-vine) chdir "0"
-(dir-rm-vine) mkdir "1"
-(dir-rm-vine) chdir "1"
-(dir-rm-vine) mkdir "2"
-(dir-rm-vine) chdir "2"
-(dir-rm-vine) mkdir "3"
-(dir-rm-vine) chdir "3"
-(dir-rm-vine) mkdir "4"
-(dir-rm-vine) chdir "4"
-(dir-rm-vine) mkdir "5"
-(dir-rm-vine) chdir "5"
-(dir-rm-vine) mkdir "6"
-(dir-rm-vine) chdir "6"
-(dir-rm-vine) mkdir "7"
-(dir-rm-vine) chdir "7"
-(dir-rm-vine) mkdir "8"
-(dir-rm-vine) chdir "8"
-(dir-rm-vine) mkdir "9"
-(dir-rm-vine) chdir "9"
-(dir-rm-vine) create "test"
-(dir-rm-vine) chdir "/"
-(dir-rm-vine) open "/0/1/2/3/4/5/6/7/8/9/test"
-(dir-rm-vine) close "/0/1/2/3/4/5/6/7/8/9/test"
-(dir-rm-vine) remove "/0/1/2/3/4/5/6/7/8/9/test"
-(dir-rm-vine) remove "/0/1/2/3/4/5/6/7/8/9"
-(dir-rm-vine) remove "/0/1/2/3/4/5/6/7/8"
-(dir-rm-vine) remove "/0/1/2/3/4/5/6/7"
-(dir-rm-vine) remove "/0/1/2/3/4/5/6"
-(dir-rm-vine) remove "/0/1/2/3/4/5"
-(dir-rm-vine) remove "/0/1/2/3/4"
-(dir-rm-vine) remove "/0/1/2/3"
-(dir-rm-vine) remove "/0/1/2"
-(dir-rm-vine) remove "/0/1"
-(dir-rm-vine) remove "/0"
-(dir-rm-vine) open "/0/1/2/3/4/5/6/7/8/9/test" (must return -1)
-(dir-rm-vine) end
-EOF
index f8f00e6a3491f6af87a18bcf89b27c4fe9fdfc38..e1c89167d716cc6f04fde32815d3ff09acf2c0af 100644 (file)
@@ -9,3 +9,5 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (dir-rmdir) chdir "a" (must return false)
 (dir-rmdir) end
 EOF
+check_archive ({});
+pass;
index 8b5cffd624c80538cdf7bac3b4dace4b00e2ded3..8123d19b0d7d8d9a9f62aa6caae5d4624d7a868e 100644 (file)
@@ -8,3 +8,5 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (dir-under-file) mkdir "abc" (must return false)
 (dir-under-file) end
 EOF
+check_archive ({"abc" => ['']});
+pass;
diff --git a/src/tests/filesys/extended/dir-vine.c b/src/tests/filesys/extended/dir-vine.c
new file mode 100644 (file)
index 0000000..8a31c38
--- /dev/null
@@ -0,0 +1,85 @@
+/* Create a very deep "vine" of directories: /dir0/dir1/dir2/...
+   and an ordinary file in each of them, until we fill up the
+   disk.
+   
+   Then delete most of them, for two reasons.  First, "tar"
+   limits file names to 100 characters (which could be extended
+   to 256 without much trouble).  Second, a full disk has no room
+   for the tar archive. */
+
+#include <string.h>
+#include <stdio.h>
+#include <syscall.h>
+#include "tests/lib.h"
+#include "tests/main.h"
+
+void
+test_main (void) 
+{
+  int i;
+
+  msg ("creating many levels of files and directories...");
+  quiet = true;
+  CHECK (mkdir ("start"), "mkdir \"start\"");
+  CHECK (chdir ("start"), "chdir \"start\"");
+  for (i = 0; ; i++) 
+    {
+      char name[3][READDIR_MAX_LEN + 1];
+      char file_name[16], dir_name[16];
+      char contents[128];
+      int fd;
+
+      /* Create file. */
+      snprintf (file_name, sizeof file_name, "file%d", i);
+      if (!create (file_name, 0))
+        break;
+      CHECK ((fd = open (file_name)) > 1, "open \"%s\"", file_name);
+      snprintf (contents, sizeof contents, "contents %d\n", i);
+      if (write (fd, contents, strlen (contents)) != (int) strlen (contents)) 
+        {
+          CHECK (remove (file_name), "remove \"%s\"", file_name);
+          close (fd);
+          break;
+        }
+      close (fd);
+      
+      /* Create directory. */
+      snprintf (dir_name, sizeof dir_name, "dir%d", i);
+      if (!mkdir (dir_name)) 
+        {
+          CHECK (remove (file_name), "remove \"%s\"", file_name);
+          break; 
+        }
+
+      /* Check for file and directory. */
+      CHECK ((fd = open (".")) > 1, "open \".\"");
+      CHECK (readdir (fd, name[0]), "readdir \".\"");
+      CHECK (readdir (fd, name[1]), "readdir \".\"");
+      CHECK (!readdir (fd, name[2]), "readdir \".\" (should fail)");
+      CHECK ((!strcmp (name[0], dir_name) && !strcmp (name[1], file_name))
+             || (!strcmp (name[1], dir_name) && !strcmp (name[0], file_name)),
+             "names should be \"%s\" and \"%s\", "
+             "actually \"%s\" and \"%s\"",
+             file_name, dir_name, name[0], name[1]);
+      close (fd);
+
+      /* Descend into directory. */
+      CHECK (chdir (dir_name), "chdir \"%s\"", dir_name);
+    }
+  CHECK (i > 200, "created files and directories only to level %d", i);
+  quiet = false;
+
+  msg ("removing all but top 10 levels of files and directories...");
+  quiet = true;
+  while (i-- > 10) 
+    {
+      char file_name[16], dir_name[16];
+
+      snprintf (file_name, sizeof file_name, "file%d", i);
+      snprintf (dir_name, sizeof dir_name, "dir%d", i);
+      CHECK (chdir (".."), "chdir \"..\"");
+      CHECK (remove (dir_name), "remove \"%s\"", dir_name);
+      CHECK (remove (file_name), "remove \"%s\"", file_name);
+    }
+  quiet = false;
+}
diff --git a/src/tests/filesys/extended/dir-vine.ck b/src/tests/filesys/extended/dir-vine.ck
new file mode 100644 (file)
index 0000000..d18b664
--- /dev/null
@@ -0,0 +1,44 @@
+# -*- perl -*-
+use strict;
+use warnings;
+use tests::tests;
+check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
+(dir-vine) begin
+(dir-vine) creating many levels of files and directories...
+(dir-vine) removing all but top 10 levels of files and directories...
+(dir-vine) end
+EOF
+
+# The archive should look like this:
+#
+# -rw-r--r-- 0/0           40642 2006-01-01 00:00:00 dir-vine
+# -rw-r--r-- 0/0           42479 2006-01-01 00:00:00 tar
+# drwxr-xr-x 0/0               0 2006-01-01 00:00:00 start
+# -rw-r--r-- 0/0              11 2006-01-01 00:00:00 start/file0
+# drwxr-xr-x 0/0               0 2006-01-01 00:00:00 start/dir0
+# -rw-r--r-- 0/0              11 2006-01-01 00:00:00 start/dir0/file1
+# drwxr-xr-x 0/0               0 2006-01-01 00:00:00 start/dir0/dir1
+# -rw-r--r-- 0/0              11 2006-01-01 00:00:00 start/dir0/dir1/file2
+# drwxr-xr-x 0/0               0 2006-01-01 00:00:00 start/dir0/dir1/dir2
+# -rw-r--r-- 0/0              11 2006-01-01 00:00:00 start/dir0/dir1/dir2/file3
+# drwxr-xr-x 0/0               0 2006-01-01 00:00:00 start/dir0/dir1/dir2/dir3
+# -rw-r--r-- 0/0              11 2006-01-01 00:00:00 start/dir0/dir1/dir2/dir3/file4
+# drwxr-xr-x 0/0               0 2006-01-01 00:00:00 start/dir0/dir1/dir2/dir3/dir4
+# -rw-r--r-- 0/0              11 2006-01-01 00:00:00 start/dir0/dir1/dir2/dir3/dir4/file5
+# drwxr-xr-x 0/0               0 2006-01-01 00:00:00 start/dir0/dir1/dir2/dir3/dir4/dir5
+# -rw-r--r-- 0/0              11 2006-01-01 00:00:00 start/dir0/dir1/dir2/dir3/dir4/dir5/file6
+# drwxr-xr-x 0/0               0 2006-01-01 00:00:00 start/dir0/dir1/dir2/dir3/dir4/dir5/dir6
+# -rw-r--r-- 0/0              11 2006-01-01 00:00:00 start/dir0/dir1/dir2/dir3/dir4/dir5/dir6/file7
+# drwxr-xr-x 0/0               0 2006-01-01 00:00:00 start/dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7
+# -rw-r--r-- 0/0              11 2006-01-01 00:00:00 start/dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/file8
+# drwxr-xr-x 0/0               0 2006-01-01 00:00:00 start/dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8
+# -rw-r--r-- 0/0              11 2006-01-01 00:00:00 start/dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/file9
+# drwxr-xr-x 0/0               0 2006-01-01 00:00:00 start/dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9
+my ($dir) = {};
+my ($root) = {"start" => $dir};
+for (my ($i) = 0; $i < 10; $i++) {
+    $dir->{"file$i"} = ["contents $i\n"];
+    $dir = $dir->{"dir$i"} = {};
+}
+check_archive ($root);
+pass;
index 54d7f6ce166e22050d1497001cbe5cd4e30e2bd6..c20ca4c34aaae267f4c9f309e49f40e035353711 100644 (file)
@@ -10,3 +10,5 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (grow-create) close "blargle"
 (grow-create) end
 EOF
+check_archive ({"blargle" => ['']});
+pass;
index 4214eec942d9663268d38b0146d28fa2168c3b97..635e1bee185127b7f47eb00a97fe47ae09822eb5 100644 (file)
@@ -2,6 +2,7 @@
 use strict;
 use warnings;
 use tests::tests;
+use tests::random;
 check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (grow-dir-lg) begin
 (grow-dir-lg) mkdir /x
@@ -57,3 +58,7 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (grow-dir-lg) creating and checking "/x/file49"
 (grow-dir-lg) end
 EOF
+my ($fs);
+$fs->{'x'}{"file$_"} = [random_bytes (512)] foreach 0...49;
+check_archive ($fs);
+pass;
index 0a70837a27198f0691366a4c6799a01d2c5d740d..057bb2e3380d7ffea2917b82bfc0a68b8732563e 100644 (file)
@@ -2,6 +2,7 @@
 use strict;
 use warnings;
 use tests::tests;
+use tests::random;
 check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (grow-file-size) begin
 (grow-file-size) create "testfile"
@@ -13,3 +14,6 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (grow-file-size) close "testfile"
 (grow-file-size) end
 EOF
+my ($string);
+check_archive ({"testfile" => [random_bytes (2134)]});
+pass;
index d44b244eed2268d8c48373fe501e1729359506cf..2affdddddc2e639156b231820f7e01f6ae9b2fb4 100644 (file)
@@ -2,6 +2,7 @@
 use strict;
 use warnings;
 use tests::tests;
+use tests::random;
 check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (grow-root-lg) begin
 (grow-root-lg) creating and checking "file0"
@@ -56,3 +57,7 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (grow-root-lg) creating and checking "file49"
 (grow-root-lg) end
 EOF
+my ($fs);
+$fs->{"file$_"} = [random_bytes (512)] foreach 0...49;
+check_archive ($fs);
+pass;
index d9d33ffe6f4c1092fd3641820255dee4027fc362..8eb59e4dc9a1c92092ec3a6eb541fa9d38296f51 100644 (file)
@@ -2,6 +2,7 @@
 use strict;
 use warnings;
 use tests::tests;
+use tests::random;
 check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (grow-root-sm) begin
 (grow-root-sm) creating and checking "file0"
@@ -26,3 +27,7 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (grow-root-sm) creating and checking "file19"
 (grow-root-sm) end
 EOF
+my ($fs);
+$fs->{"file$_"} = [random_bytes (512)] foreach 0...19;
+check_archive ($fs);
+pass;
index 659aeff543cbea942c95c5a942f574f3d1268137..6276c79712a6a38c857ffd63c30a20c1d4fabeba 100644 (file)
@@ -2,6 +2,7 @@
 use strict;
 use warnings;
 use tests::tests;
+use tests::random;
 check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (grow-seq-lg) begin
 (grow-seq-lg) create "testme"
@@ -13,3 +14,5 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (grow-seq-lg) close "testme"
 (grow-seq-lg) end
 EOF
+check_archive ({"testme" => [random_bytes (72943)]});
+pass;
index 242aa0e238ff861ee9d896225d0089812e4c8f54..8dd2c26e0d7f4aa0d1282f1e6a07560de195c82e 100644 (file)
@@ -2,6 +2,7 @@
 use strict;
 use warnings;
 use tests::tests;
+use tests::random;
 check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (grow-seq-sm) begin
 (grow-seq-sm) create "testme"
@@ -13,3 +14,5 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (grow-seq-sm) close "testme"
 (grow-seq-sm) end
 EOF
+check_archive ({"testme" => [random_bytes (5678)]});
+pass;
index 2b2d950163c1b3bd721d79384805ec43fd636893..9c6315f796080eb4798642a46b0073405f08d3d6 100644 (file)
@@ -14,3 +14,5 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (grow-sparse) close "testfile"
 (grow-sparse) end
 EOF
+check_archive ({"testfile" => ["\0" x 76543]});
+pass;
index 3e8abcfc8f1749706a481f04bcda593fe3bb340d..cd03efbd8477157a60362f69996bada034931177 100644 (file)
@@ -2,6 +2,7 @@
 use strict;
 use warnings;
 use tests::tests;
+use tests::random;
 check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (grow-tell) begin
 (grow-tell) create "foobar"
@@ -13,3 +14,5 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (grow-tell) close "foobar"
 (grow-tell) end
 EOF
+check_archive ({"foobar" => [random_bytes (2134)]});
+pass;
diff --git a/src/tests/filesys/extended/grow-too-big.c b/src/tests/filesys/extended/grow-too-big.c
deleted file mode 100644 (file)
index a908e45..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/* Checks that trying to grow a file beyond the capacity of the
-   file system behaves reasonably (does not crash). */
-
-#include <limits.h>
-#include <syscall.h>
-#include "tests/lib.h"
-#include "tests/main.h"
-
-void
-test_main (void) 
-{
-  const char *file_name = "fumble";
-  char zero = 0;
-  int fd;
-  
-  CHECK (create (file_name, 0), "create \"%s\"", file_name);
-  CHECK ((fd = open (file_name)) > 1, "open \"%s\"", file_name);
-  msg ("seek \"%s\"", file_name);
-  seek (fd, UINT_MAX);
-  msg ("write \"%s\"", file_name);
-  write (fd, &zero, 1);
-  msg ("close \"%s\"", file_name);
-  close (fd);
-}
diff --git a/src/tests/filesys/extended/grow-too-big.ck b/src/tests/filesys/extended/grow-too-big.ck
deleted file mode 100644 (file)
index 9a4027c..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-# -*- perl -*-
-use strict;
-use warnings;
-use tests::tests;
-check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
-(grow-too-big) begin
-(grow-too-big) create "fumble"
-(grow-too-big) open "fumble"
-(grow-too-big) seek "fumble"
-(grow-too-big) write "fumble"
-(grow-too-big) close "fumble"
-(grow-too-big) end
-EOF
index d62d9fa0fd549a0ece2741ad01847cfdab2f54eb..b238d80f7fc0b182a6b5a3530ca4f712781f4704 100644 (file)
@@ -2,6 +2,7 @@
 use strict;
 use warnings;
 use tests::tests;
+use tests::random;
 check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (grow-two-files) begin
 (grow-two-files) create "a"
@@ -19,3 +20,7 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (grow-two-files) close "b"
 (grow-two-files) end
 EOF
+my ($a) = random_bytes (8143);
+my ($b) = random_bytes (8143);
+check_archive ({"a" => [$a], "b" => [$b]});
+pass;
index 41b6e8a4c49e4d428a39625df8e9a32de6a1f0f5..7a70299266e45982da330c50e1dd4ef040e52fd6 100644 (file)
@@ -2,6 +2,7 @@
 use strict;
 use warnings;
 use tests::tests;
+use tests::random;
 check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (syn-rw) begin
 (syn-rw) create "logfile"
@@ -16,3 +17,6 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (syn-rw) wait for child 4 of 4 returned 3 (expected 3)
 (syn-rw) end
 EOF
+check_archive ({"child-syn-rw" => "tests/filesys/extended/child-syn-rw",
+               "logfile" => [random_bytes (8 * 512)]});
+pass;
diff --git a/src/tests/filesys/extended/tar.c b/src/tests/filesys/extended/tar.c
new file mode 100644 (file)
index 0000000..193c373
--- /dev/null
@@ -0,0 +1,250 @@
+/* tar.c
+
+   Creates a tar archive. */
+
+#include <syscall.h>
+#include <stdio.h>
+#include <string.h>
+
+static void usage (void);
+static bool make_tar_archive (const char *archive_name,
+                              char *files[], size_t file_cnt);
+
+int
+main (int argc, char *argv[]) 
+{
+  if (argc < 3)
+    usage ();
+
+  return (make_tar_archive (argv[1], argv + 2, argc - 2)
+          ? EXIT_SUCCESS : EXIT_FAILURE);
+}
+
+static void
+usage (void) 
+{
+  printf ("tar, tar archive creator\n"
+          "Usage: tar ARCHIVE FILE...\n"
+          "where ARCHIVE is the tar archive to create\n"
+          "  and FILE... is a list of files or directories to put into it.\n"
+          "(ARCHIVE itself will not be included in the archive, even if it\n"
+          "is in a directory to be archived.)\n");
+  exit (EXIT_FAILURE);
+}
+\f
+static bool archive_file (char file_name[], size_t file_name_size,
+                          int archive_fd, bool *write_error);
+
+static bool archive_ordinary_file (const char *file_name, int file_fd,
+                                   int archive_fd, bool *write_error);
+static bool archive_directory (char file_name[], size_t file_name_size,
+                               int file_fd, int archive_fd, bool *write_error);
+static bool write_header (const char *file_name,
+                          char type_flag, int size, unsigned mode,
+                          int archive_fd, bool *write_error);
+
+static bool do_write (int fd, const char *buffer, int size, bool *write_error);
+
+static bool
+make_tar_archive (const char *archive_name, char *files[], size_t file_cnt) 
+{
+  static const char zeros[512];
+  int archive_fd;
+  bool success;
+  bool write_error = false;
+  size_t i;
+  
+  if (!create (archive_name, 0)) 
+    {
+      printf ("%s: create failed\n", archive_name);
+      return false;
+    }
+  archive_fd = open (archive_name);
+  if (archive_fd < 0)
+    {
+      printf ("%s: open failed\n", archive_name);
+      return false;
+    }
+
+  for (i = 0; i < file_cnt; i++) 
+    {
+      char file_name[128];
+      
+      strlcpy (file_name, files[i], sizeof file_name);
+      if (!archive_file (file_name, sizeof file_name,
+                         archive_fd, &write_error))
+        success = false;
+    }
+
+  if (!do_write (archive_fd, zeros, 512, &write_error)
+      || !do_write (archive_fd, zeros, 512, &write_error)) 
+    success = false;
+
+  close (archive_fd);
+
+  return success;
+}
+
+static bool
+archive_file (char file_name[], size_t file_name_size,
+              int archive_fd, bool *write_error) 
+{
+  int file_fd = open (file_name);
+  if (file_fd >= 0) 
+    {
+      bool success;
+
+      if (inumber (file_fd) != inumber (archive_fd)) 
+        {
+          if (!isdir (file_fd))
+            success = archive_ordinary_file (file_name, file_fd,
+                                             archive_fd, write_error);
+          else
+            success = archive_directory (file_name, file_name_size, file_fd,
+                                         archive_fd, write_error);      
+        }
+      else
+        {
+          /* Nothing to do: don't try to archive the archive file. */
+          success = true;
+        }
+  
+      close (file_fd);
+
+      return success;
+    }
+  else
+    {
+      printf ("%s: open failed\n", file_name);
+      return false;
+    }
+}
+
+static bool
+archive_ordinary_file (const char *file_name, int file_fd,
+                       int archive_fd, bool *write_error)
+{
+  bool read_error = false;
+  bool success = true;
+  int file_size = filesize (file_fd);
+
+  if (!write_header (file_name, '0', file_size, 0644, archive_fd, write_error))
+    return false;
+
+  while (file_size > 0) 
+    {
+      static char buf[512];
+      int chunk_size = file_size > 512 ? 512 : file_size;
+      int read_retval = read (file_fd, buf, chunk_size);
+      int bytes_read = read_retval > 0 ? read_retval : 0;
+
+      if (bytes_read != chunk_size && !read_error) 
+        {
+          printf ("%s: read error\n", file_name);
+          read_error = true;
+          success = false;
+        }
+
+      memset (buf + bytes_read, 0, 512 - bytes_read);
+      if (!do_write (archive_fd, buf, 512, write_error))
+        success = false;
+
+      file_size -= chunk_size;
+    }
+
+  return success;
+}
+
+static bool
+archive_directory (char file_name[], size_t file_name_size, int file_fd,
+                   int archive_fd, bool *write_error)
+{
+  size_t dir_len;
+  bool success = true;
+
+  dir_len = strlen (file_name);
+  if (dir_len + 1 + READDIR_MAX_LEN + 1 > file_name_size) 
+    {
+      printf ("%s: file name too long\n", file_name);
+      return false;
+    }
+
+  if (!write_header (file_name, '5', 0, 0755, archive_fd, write_error))
+    return false;
+      
+  file_name[dir_len] = '/';
+  while (readdir (file_fd, &file_name[dir_len + 1])) 
+    if (!archive_file (file_name, file_name_size, archive_fd, write_error))
+      success = false;
+  file_name[dir_len] = '\0';
+
+  return success;
+}
+
+static bool
+write_header (const char *file_name,
+              char type_flag, int size, unsigned mode,
+              int archive_fd, bool *write_error) 
+{
+  static char header[512];
+  unsigned chksum;
+  size_t i;
+
+  memset (header, 0, sizeof header);
+
+/* Drop confusing and possibly dangerous prefixes from
+   FILE_NAME. */
+  while (*file_name == '/'
+         || !memcmp (file_name, "./", 2)
+         || !memcmp (file_name, "../", 3))
+    file_name = strchr (file_name, '/') + 1;
+  if (*file_name == '\0') 
+    {
+      /* Dropped *everything* from FILE_NAME.
+         Should only be possible for a directory. */
+      ASSERT (type_flag == '5');
+      return true; 
+    }
+  else if (strlen (file_name) > 99)
+    {
+      printf ("%s: file name too long\n", file_name);
+      return false;
+    }
+
+  /* Fill in header except for final checksum. */
+  strlcpy (header, file_name, 100);                 /* name */
+  snprintf (header + 100, 8, "%07o", mode);         /* mode */
+  strlcpy (header + 108, "0000000", 8);             /* uid */
+  strlcpy (header + 116, "0000000", 8);             /* gid */
+  snprintf (header + 124, 12, "%011o", size);       /* size */
+  snprintf (header + 136, 12, "%011o", 1136102400); /* mtime (2006-01-01) */
+  memset (header + 148, ' ', 8);                    /* chksum */
+  header[156] = type_flag;                          /* typeflag */
+  strlcpy (header + 257, "ustar", 6);               /* magic */
+  strlcpy (header + 263, "00", 3);                  /* version */
+
+  /* Compute and fill in final checksum. */
+  chksum = 0;
+  for (i = 0; i < 512; i++)
+    chksum += (uint8_t) header[i];
+  snprintf (header + 148, 8, "%07o", chksum);
+
+  /* Write header. */
+  return do_write (archive_fd, header, 512, write_error);
+}
+
+static bool
+do_write (int fd, const char *buffer, int size, bool *write_error) 
+{
+  if (write (fd, buffer, size) == size) 
+    return true;
+  else
+    {
+      if (!*write_error) 
+        {
+          printf ("error writing archive\n");
+          *write_error = true; 
+        }
+      return false; 
+    }
+}
index 858d8a4b50c58e1698bc5181024ea3a5bf012ada..74b69054936205970c150197bcfd1f023f45f79a 100644 (file)
@@ -2,6 +2,7 @@ use strict;
 use warnings;
 use tests::Algorithm::Diff;
 use File::Temp 'tempfile';
+use Fcntl qw(SEEK_SET SEEK_CUR);
 
 sub fail;
 sub pass;
@@ -11,42 +12,45 @@ our ($test, $src_dir) = @ARGV;
 
 my ($msg_file) = tempfile ();
 select ($msg_file);
+\f
+# Generic testing.
 
 sub check_expected {
     my ($expected) = pop @_;
     my (@options) = @_;
     my (@output) = read_text_file ("$test.output");
-    common_checks (@output);
-    compare_output (@options, \@output, $expected);
+    common_checks ("run", @output);
+    compare_output ("run", @options, \@output, $expected);
 }
 
 sub common_checks {
-    my (@output) = @_;
+    my ($run, @output) = @_;
 
-    fail "No output at all\n" if @output == 0;
+    fail "\u$run produced no output at all\n" if @output == 0;
 
-    check_for_panic (@output);
-    check_for_keyword ("FAIL", @output);
-    check_for_triple_fault (@output);
-    check_for_keyword ("TIMEOUT", @output);
+    check_for_panic ($run, @output);
+    check_for_keyword ($run, "FAIL", @output);
+    check_for_triple_fault ($run, @output);
+    check_for_keyword ($run, "TIMEOUT", @output);
 
-    fail "Didn't start up properly: no \"Pintos booting\" startup message\n"
+    fail "\u$run didn't start up properly: no \"Pintos booting\" message\n"
       if !grep (/Pintos booting with.*kB RAM\.\.\./, @output);
-    fail "Didn't start up properly: no \"Boot complete\" startup message\n"
+    fail "\u$run didn't start up properly: no \"Boot complete\" message\n"
       if !grep (/Boot complete/, @output);
-    fail "Didn't shut down properly: no \"Timer: # ticks\" shutdown message\n"
+    fail "\u$run didn't shut down properly: no \"Timer: # ticks\" message\n"
       if !grep (/Timer: \d+ ticks/, @output);
-    fail "Didn't shut down properly: no \"Powering off\" shutdown message\n"
+    fail "\u$run didn't shut down properly: no \"Powering off\" message\n"
       if !grep (/Powering off/, @output);
 }
 
 sub check_for_panic {
-    my (@output) = @_;
+    my ($run, @output) = @_;
 
     my ($panic) = grep (/PANIC/, @output);
     return unless defined $panic;
 
-    print "Kernel panic: ", substr ($panic, index ($panic, "PANIC")), "\n";
+    print "Kernel panic in $run: ", substr ($panic, index ($panic, "PANIC")),
+      "\n";
 
     my (@stack_line) = grep (/Call stack:/, @output);
     if (@stack_line != 0) {
@@ -86,7 +90,7 @@ EOF
 }
 
 sub check_for_keyword {
-    my ($keyword, @output) = @_;
+    my ($run, $keyword, @output) = @_;
     
     my ($kw_line) = grep (/$keyword/, @output);
     return unless defined $kw_line;
@@ -94,18 +98,19 @@ sub check_for_keyword {
     # Most output lines are prefixed by (test-name).  Eliminate this
     # from our message for brevity.
     $kw_line =~ s/^\([^\)]+\)\s+//;
-    print "$kw_line\n";
+    print "$run: $kw_line\n";
 
     fail;
 }
 
 sub check_for_triple_fault {
-    my (@output) = @_;
+    my ($run, @output) = @_;
 
-    return unless grep (/Pintos booting/, @output) > 1;
+    my ($reboots) = grep (/Pintos booting/, @output) - 1;
+    return unless $reboots > 0;
 
     print <<EOF;
-Pintos spontaneously rebooted during this test.
+\u$run spontaneously rebooted $reboots times.
 This is most often caused by unhandled page faults.
 EOF
 
@@ -114,19 +119,35 @@ EOF
 
 # Get @output without header or trailer.
 sub get_core_output {
+    my ($run, @output) = @_;
     my ($p);
-    do { $p = shift; } while (defined ($p) && $p !~ /^Executing '.*':$/);
-    do { $p = pop; } while (defined ($p) && $p !~ /^Execution of '.*' complete.$/);
-    return @_;
+
+    my ($process);
+    my ($start);
+    for my $i (0...$#_) {
+       $start = $i + 1, last
+         if ($process) = $output[$i] =~ /^Executing '(\S+).*':$/;
+    }
+
+    my ($end);
+    for my $i ($start...$#output) {
+       $end = $i - 1, last if $output[$i] =~ /^Execution of '.*' complete.$/;
+    }
+
+    fail "\u$run didn't start a thread or process\n" if !defined $start;
+    fail "\u$run started '$process' but it never finished\n" if !defined $end;
+
+    return @output[$start...$end];
 }
 
 sub compare_output {
+    my ($run) = shift @_;
     my ($expected) = pop @_;
     my ($output) = pop @_;
     my (%options) = @_;
 
-    my (@output) = get_core_output (@$output);
-    fail "'$test' didn't run or didn't produce any output\n" if !@output;
+    my (@output) = get_core_output ($run, @$output);
+    fail "\u$run didn't produce any output" if !@output;
 
     if (exists $options{IGNORE_EXIT_CODES}) {
        delete $options{IGNORE_EXIT_CODES};
@@ -137,8 +158,12 @@ sub compare_output {
     my ($msg);
 
     # Compare actual output against each allowed output.
-    foreach my $exp_string (@$expected) {
-       my (@expected) = split ("\n", $exp_string);
+    if (ref ($expected) eq 'ARRAY') {
+       my ($i) = 0;
+       $expected = {map ((++$i => $_), @$expected)};
+    }
+    foreach my $key (keys %$expected) {
+       my (@expected) = split ("\n", $expected->{$key});
 
        $msg .= "Acceptable output:\n";
        $msg .= join ('', map ("  $_\n", @expected));
@@ -150,7 +175,7 @@ sub compare_output {
            for (my ($i) = 0; $i <= $#expected; $i++) {
                $eq = 0 if $output[$i] ne $expected[$i];
            }
-           pass if $eq;
+           return $key if $eq;
        }
 
        # They differ.  Output a diff.
@@ -173,6 +198,354 @@ sub compare_output {
     # Failed to match.  Report failure.
     fail "Test output failed to match any acceptable form.\n\n$msg";
 }
+\f
+# File system extraction.
+
+# check_archive (\%CONTENTS)
+#
+# Checks that the extracted file system's contents match \%CONTENTS.
+# Each key in the hash is a file name.  Each value may be:
+#
+#      - $FILE: Name of a host file containing the expected contents.
+#
+#      - [$FILE, $OFFSET, $LENGTH]: An excerpt of host file $FILE
+#        comprising the $LENGTH bytes starting at $OFFSET.
+#
+#      - [$CONTENTS]: The literal expected file contents, as a string.
+#
+#       - {SUBDIR}: A subdirectory, in the same form described here,
+#         recursively.
+sub check_archive {
+    my ($expected_hier) = @_;
+    my (@output) = read_text_file ("$test.get-output");
+    common_checks ("file system extraction run", @output);
+
+    @output = get_core_output ("file system extraction run", @output);
+    @output = grep (!/^[a-zA-Z0-9-_]+: exit\(\d+\)$/, @output);
+    fail join ("\n", "Error extracting file system:", @output) if @output;
+
+    my ($test_base_name) = $test;
+    $test_base_name =~ s%.*/%%;
+    $expected_hier->{$test_base_name} = $test;
+    $expected_hier->{'tar'} = 'tests/filesys/extended/tar';
+
+    my (%expected) = normalize_fs (flatten_hierarchy ($expected_hier, ""));
+    my (%actual) = read_tar ("$test.tar");
+
+    my ($errors) = 0;
+    foreach my $name (sort keys %expected) {
+       if (exists $actual{$name}) {
+           if (is_dir ($actual{$name}) && !is_dir ($expected{$name})) {
+               print "$name is a directory but should be an ordinary file.\n";
+               $errors++;
+           } elsif (!is_dir ($actual{$name}) && is_dir ($expected{$name})) {
+               print "$name is an ordinary file but should be a directory.\n";
+               $errors++;
+           }
+       } else {
+           print "$name is missing from the file system.\n";
+           $errors++;
+       }
+    }
+    foreach my $name (sort keys %actual) {
+       if (!exists $expected{$name}) {
+           if ($name =~ /^[[:print:]]+$/) {
+               print "$name exists in the file system but it should not.\n";
+           } else {
+               my ($esc_name) = $name;
+               $esc_name =~ s/[^[:print:]]/./g;
+               print <<EOF;
+$esc_name exists in the file system but should not.  (The expected name
+of this file contains unusual characters that were printed as `.'.)
+EOF
+           }
+           $errors++;
+       }
+    }
+    if ($errors) {
+       print "\nActual contents of file system:\n";
+       print_fs (%actual);
+       print "\nExpected contents of file system:\n";
+       print_fs (%expected);
+    } else {
+       foreach my $name (sort keys %expected) {
+           if (!is_dir ($expected{$name})) {
+               my ($exp_file, $exp_length) = open_file ($expected{$name});
+               my ($act_file, $act_length) = open_file ($actual{$name});
+               $errors += !compare_files ($exp_file, $exp_length,
+                                          $act_file, $act_length, $name,
+                                          !$errors);
+               close ($exp_file);
+               close ($act_file);
+           }
+       }
+    }
+    fail "Extracted file system contents are not correct.\n" if $errors;
+}
+
+# open_file ([$FILE, $OFFSET, $LENGTH])
+# open_file ([$CONTENTS])
+#
+# Opens a file for the contents passed in, which must be in one of
+# the two above forms that correspond to check_archive() arguments.
+#
+# Returns ($HANDLE, $LENGTH), where $HANDLE is the file's handle and
+# $LENGTH is the number of bytes in the file's content.
+sub open_file {
+    my ($value) = @_;
+    die if ref ($value) ne 'ARRAY';
+
+    my ($file) = tempfile ();
+    my ($length);
+    if (@$value == 1) {
+       $length = length ($value->[0]);
+       $file = tempfile ();
+       syswrite ($file, $value->[0]) == $length
+         or die "writing temporary file: $!\n";
+       sysseek ($file, 0, SEEK_SET);
+    } elsif (@$value == 3) {
+       $length = $value->[2];
+       open ($file, '<', $value->[0]) or die "$value->[0]: open: $!\n";
+       die "$value->[0]: file is smaller than expected\n"
+         if -s $file < $value->[1] + $length;
+       sysseek ($file, $value->[1], SEEK_SET);
+    } else {
+       die;
+    }
+    return ($file, $length);
+}
+
+# compare_files ($A, $A_SIZE, $B, $B_SIZE, $NAME, $VERBOSE)
+#
+# Compares $A_SIZE bytes in $A to $B_SIZE bytes in $B.
+# ($A and $B are handles.)
+# If their contents differ, prints a brief message describing
+# the differences, using $NAME to identify the file.
+# The message contains more detail if $VERBOSE is nonzero.
+# Returns 1 if the contents are identical, 0 otherwise.
+sub compare_files {
+    my ($a, $a_size, $b, $b_size, $name, $verbose) = @_;
+    my ($ofs) = 0;
+    select(STDOUT);
+    for (;;) {
+       my ($a_amt) = $a_size >= 1024 ? 1024 : $a_size;
+       my ($b_amt) = $b_size >= 1024 ? 1024 : $b_size;
+       my ($a_data, $b_data);
+       if (!defined (sysread ($a, $a_data, $a_amt))
+           || !defined (sysread ($b, $b_data, $b_amt))) {
+           die "reading $name: $!\n";
+       }
+
+       my ($a_len) = length $a_data;
+       my ($b_len) = length $b_data;
+       last if $a_len == 0 && $b_len == 0;
+
+       if ($a_data ne $b_data) {
+           my ($min_len) = $a_len < $b_len ? $a_len : $b_len;
+           my ($diff_ofs);
+           for ($diff_ofs = 0; $diff_ofs < $min_len; $diff_ofs++) {
+               last if (substr ($a_data, $diff_ofs, 1)
+                        ne substr ($b_data, $diff_ofs, 1));
+           }
+
+           printf "\nFile $name differs from expected "
+             . "starting at offset 0x%x.\n", $ofs + $diff_ofs;
+           if ($verbose ) {
+               print "Expected contents:\n";
+               hex_dump (substr ($a_data, $diff_ofs, 64), $ofs + $diff_ofs);
+               print "Actual contents:\n";
+               hex_dump (substr ($b_data, $diff_ofs, 64), $ofs + $diff_ofs);
+           }
+           return 0;
+       }
+
+       $ofs += $a_len;
+       $a_size -= $a_len;
+       $b_size -= $b_len;
+    }
+    return 1;
+}
+
+# hex_dump ($DATA, $OFS)
+#
+# Prints $DATA in hex and text formats.
+# The first byte of $DATA corresponds to logical offset $OFS
+# in whatever file the data comes from.
+sub hex_dump {
+    my ($data, $ofs) = @_;
+
+    if ($data eq '') {
+       printf "  (File ends at offset %08x.)\n", $ofs;
+       return;
+    }
+
+    my ($per_line) = 16;
+    while ((my $size = length ($data)) > 0) {
+       my ($start) = $ofs % $per_line;
+       my ($end) = $per_line;
+       $end = $start + $size if $end - $start > $size;
+       my ($n) = $end - $start;
+
+       printf "0x%08x  ", int ($ofs / $per_line) * $per_line;
+
+       # Hex version.
+       print "   " x $start;
+       for my $i ($start...$end - 1) {
+           printf "%02x", ord (substr ($data, $i - $start, 1));
+           print $i == $per_line / 2 - 1 ? '-' : ' ';
+       }
+       print "   " x ($per_line - $end);
+
+       # Character version.
+       my ($esc_data) = substr ($data, 0, $n);
+       $esc_data =~ s/[^[:print:]]/./g;
+       print "|", " " x $start, $esc_data, " " x ($per_line - $end), "|";
+
+       print "\n";
+
+       $data = substr ($data, $n);
+       $ofs += $n;
+    }
+}
+
+# print_fs (%FS)
+#
+# Prints a list of files in %FS, which must be a file system
+# as flattened by flatten_hierarchy() and normalized by
+# normalize_fs().
+sub print_fs {
+    my (%fs) = @_;
+    foreach my $name (sort keys %fs) {
+       my ($esc_name) = $name;
+       $esc_name =~ s/[^[:print:]]/./g;
+       print "$esc_name: ";
+       if (!is_dir ($fs{$name})) {
+           print +file_size ($fs{$name}), "-byte file";
+       } else {
+           print "directory";
+       }
+       print "\n";
+    }
+}
+
+# normalize_fs (%FS)
+#
+# Takes a file system as flattened by flatten_hierarchy().
+# Returns a similar file system in which values of the form $FILE
+# are replaced by those of the form [$FILE, $OFFSET, $LENGTH].
+sub normalize_fs {
+    my (%fs) = @_;
+    foreach my $name (keys %fs) {
+       my ($value) = $fs{$name};
+       next if is_dir ($value) || ref ($value) ne '';
+       die "can't open $value\n" if !stat $value;
+       $fs{$name} = [$value, 0, -s _];
+    }
+    return %fs;
+}
+
+# is_dir ($VALUE)
+#
+# Takes a value like one in the hash returned by flatten_hierarchy()
+# and returns 1 if it represents a directory, 0 otherwise.
+sub is_dir {
+    my ($value) = @_;
+    return ref ($value) eq '' && $value eq 'directory';
+}
+
+# file_size ($VALUE)
+#
+# Takes a value like one in the hash returned by flatten_hierarchy()
+# and returns the size of the file it represents.
+sub file_size {
+    my ($value) = @_;
+    die if is_dir ($value);
+    die if ref ($value) ne 'ARRAY';
+    return @$value > 1 ? $value->[2] : length ($value->[0]);
+}
+
+# flatten_hierarchy ($HIER_FS, $PREFIX)
+#
+# Takes a file system in the format expected by check_archive() and
+# returns a "flattened" version in which file names include all parent
+# directory names and the value of directories is just "directory".
+sub flatten_hierarchy {
+    my (%hier_fs) = %{$_[0]};
+    my ($prefix) = $_[1];
+    my (%flat_fs);
+    for my $name (keys %hier_fs) {
+       my ($value) = $hier_fs{$name};
+       if (ref $value eq 'HASH') {
+           %flat_fs = (%flat_fs, flatten_hierarchy ($value, "$prefix$name/"));
+           $flat_fs{"$prefix$name"} = 'directory';
+       } else {
+           $flat_fs{"$prefix$name"} = $value;
+       }
+    }
+    return %flat_fs;
+}
+
+# read_tar ($ARCHIVE)
+#
+# Reads the ustar-format tar file in $ARCHIVE
+# and returns a flattened file system for it.
+sub read_tar {
+    my ($archive) = @_;
+    my (%content);
+    open (ARCHIVE, '<', $archive) or die "$archive: open: $1\n";
+    for (;;) {
+       my ($header);
+       if ((my $retval = sysread (ARCHIVE, $header, 512)) != 512) {
+           die "$archive: unexpected end of file\n" if $retval >= 0;
+           die "$archive: read: $!\n";
+       }
+
+       last if $header eq "\0" x 512;
+
+       # Verify magic numbers.
+       if (substr ($header, 257, 6) ne "ustar\0"
+           || substr ($header, 263, 2) ne '00') {
+           die "$archive: corrupt ustar header\n";
+       }
+
+       # Verify checksum.
+       my ($chksum) = oct (unpack ("Z*", substr ($header, 148, 8, ' ' x 8)));
+       my ($correct_chksum) = unpack ("%32a*", $header);
+       die "$archive: bad header checksum\n" if $chksum != $correct_chksum;
+
+       # Get file name.
+       my ($name) = unpack ("Z100", $header);
+       my ($prefix) = unpack ("Z*", substr ($header, 345));
+       $name = "$prefix/$name" if $prefix ne '';
+       die "$archive: contains file with empty name" if $name eq '';
+
+       # Get type.
+       my ($typeflag) = substr ($header, 156, 1);
+       $typeflag = '0' if $typeflag eq "\0";
+       die "unknown file type '$typeflag'\n" if $typeflag !~ /[05]/;
+
+       # Get size.
+       my ($size) = oct (unpack ("Z*", substr ($header, 124, 12)));
+       die "bad size $size\n" if $size < 0;
+       $size = 0 if $typeflag eq '5';
+
+       # Store content.
+       if (exists $content{$name}) {
+           die "$archive: contains multiple entries for $name\n";
+       }
+       if ($typeflag eq '5') {
+           $content{$name} = 'directory';
+       } else {
+           my ($position) = sysseek (ARCHIVE, 0, SEEK_CUR);
+           $content{$name} = [$archive, $position, $size];
+           sysseek (ARCHIVE, int (($size + 511) / 512) * 512, SEEK_CUR);
+       }
+    }
+    close (ARCHIVE);
+    return %content;
+}
+\f
+# Utilities.
 
 sub fail {
     finish ("FAIL", @_);
@@ -183,18 +556,17 @@ sub pass {
 }
 
 sub finish {
-    my ($verdict, @rest) = @_;
+    my ($verdict, @messages) = @_;
 
-    my ($messages) = "";
     seek ($msg_file, 0, 0);
-    while (<$msg_file>) {
-       $messages .= $_;
-    }
+    push (@messages, <$msg_file>);
     close ($msg_file);
+    chomp (@messages);
 
     my ($result_fn) = "$test.result";
     open (RESULT, '>', $result_fn) or die "$result_fn: create: $!\n";
-    print RESULT "$verdict\n", $messages, @rest;
+    print RESULT "$verdict\n";
+    print RESULT "$_\n" foreach @messages;
     close (RESULT);
 
     if ($verdict eq 'PASS') {
@@ -202,7 +574,7 @@ sub finish {
     } else {
        print STDOUT "FAIL $test\n";
     }
-    print STDOUT $messages, @rest, "\n";
+    print STDOUT "$_\n" foreach @messages;
 
     exit 0;
 }
index e40ff30e84376551fd92b1dbaee9f22ffcbc4fbc..0d2bab07aefecada5942ae1e3ca9e2d4a993820d 100644 (file)
@@ -7,3 +7,4 @@ check_expected ([<<'EOF']);
 (alarm-negative) PASS
 (alarm-negative) end
 EOF
+pass;
index c62b024944b0e16d63921b836a4f04ab3b071ef7..b57c78b38163c97d84ba82e73058df1876e207f0 100644 (file)
@@ -16,3 +16,4 @@ check_expected ([<<'EOF']);
 (alarm-priority) Thread priority 21 woke up.
 (alarm-priority) end
 EOF
+pass;
index 510c07d2d209f9c9007ad23af1083525a478f613..7cec517694952a541dcf928ca3659595f2257ed7 100644 (file)
@@ -34,3 +34,4 @@ check_expected ([<<'EOF']);
 (alarm-simultaneous) iteration 4, thread 4: woke up 0 ticks later
 (alarm-simultaneous) end
 EOF
+pass;
index 6a967b4732d5cef4a2ee8ec00b1f70773783a097..a6b1a3cd77920604c6c9ff41854be7a1b347abfa 100644 (file)
@@ -7,3 +7,4 @@ check_expected ([<<'EOF']);
 (alarm-zero) PASS
 (alarm-zero) end
 EOF
+pass;
index 84d6d121c681be38da4f8784fac785e3e4f3a1c1..84b3b7f741de84841614b22b956876179f738dff 100644 (file)
@@ -3,7 +3,7 @@ sub check_alarm {
     our ($test);
 
     @output = read_text_file ("$test.output");
-    common_checks (@output);
+    common_checks ("run", @output);
 
     my (@products);
     for (my ($i) = 0; $i < $iterations; $i++) {
index e3b883afdcd00895731e70aede0eafb0b215be4c..8833a3affc0069b4c34fcd8a92f1bbdb76fae989 100644 (file)
@@ -14,3 +14,4 @@ check_expected ([<<'EOF']);
 (mlfqs-block) Block thread should have already acquired lock.
 (mlfqs-block) end
 EOF
+pass;
index db788818e35018cf3adcfff829cb11ce4b67ef20..faf0ffac0fcdf25f1ad93654b254ca04d8079fd7 100644 (file)
@@ -6,9 +6,9 @@ use tests::tests;
 our ($test);
 my (@output) = read_text_file ("$test.output");
 
-common_checks (@output);
+common_checks ("run", @output);
 
-@output = get_core_output (@output);
+@output = get_core_output ("run", @output);
 fail "missing PASS in output"
   unless grep ($_ eq '(mlfqs-load-1) PASS', @output);
 
index d2d6d63db7e931a34511fdc066c4fb6324814b9b..cb69220024ef7973a3218623a372f2e1ab3477e9 100644 (file)
@@ -7,8 +7,8 @@ use tests::threads::mlfqs;
 our ($test);
 
 my (@output) = read_text_file ("$test.output");
-common_checks (@output);
-@output = get_core_output (@output);
+common_checks ("run", @output);
+@output = get_core_output ("run", @output);
 
 # Get actual values.
 local ($_);
index 3852072ac2a1f8df9f54c03ff823b3111136ecde..2254d05467ee7a8bce10994ff10f98a91919f7f4 100644 (file)
@@ -7,8 +7,8 @@ use tests::threads::mlfqs;
 our ($test);
 my (@output) = read_text_file ("$test.output");
 
-common_checks (@output);
-@output = get_core_output (@output);
+common_checks ("run", @output);
+@output = get_core_output ("run", @output);
 
 # Get actual values.
 local ($_);
index 76b72234d8dbdd0c7009fd22e026865b8fb271b4..a2ba44d375987e7d3504adce66f1dd78efbfddf6 100644 (file)
@@ -6,8 +6,8 @@ use tests::threads::mlfqs;
 
 our ($test);
 my (@output) = read_text_file ("$test.output");
-common_checks (@output);
-@output = get_core_output (@output);
+common_checks ("run", @output);
+@output = get_core_output ("run", @output);
 
 # Get actual values.
 local ($_);
index 2ca7d09c531d7f0dc4ea55ae4e0f6aa576fcda51..184ac16a0a1c2c45304ca7580145eb067e3416a9 100644 (file)
@@ -73,8 +73,8 @@ sub check_mlfqs_fair {
     my ($nice, $maxdiff) = @_;
     our ($test);
     my (@output) = read_text_file ("$test.output");
-    common_checks (@output);
-    @output = get_core_output (@output);
+    common_checks ("run", @output);
+    @output = get_core_output ("run", @output);
 
     my (@actual);
     local ($_);
index a0c759a9ae49108f125b67a7c51ea6f620146b66..f4d9b2f34f1fdc6a3910f83b43f33ca826f1ae20 100644 (file)
@@ -11,3 +11,4 @@ check_expected ([<<'EOF']);
 (priority-change) Thread 2 should have just exited.
 (priority-change) end
 EOF
+pass;
index 580a019f50e5e9274ac3dc3689c7c441b6079a78..195c1ab4753cd22f92a86eb6291e10cb9216eca7 100644 (file)
@@ -36,3 +36,4 @@ check_expected ([<<'EOF']);
 (priority-condvar) Thread priority 21 woke up.
 (priority-condvar) end
 EOF
+pass;
index b009fd81c350a8fd1601e0c6c7a9a1715161c5d6..c9bb61b170e43ed6ebaddd7905334b837680f643 100644 (file)
@@ -13,3 +13,4 @@ check_expected ([<<'EOF']);
 (priority-donate-lower) Main thread should have priority 21.  Actual priority: 21.
 (priority-donate-lower) end
 EOF
+pass;
index d84a0ee5144ae67e11e8efc180eb2b9ee190e617..0afd20bd1397fbd1aac7b84b9eccba48ae9e42c9 100644 (file)
@@ -16,3 +16,4 @@ check_expected ([<<'EOF']);
 (priority-donate-multiple) Main thread should have priority 31.  Actual priority: 31.
 (priority-donate-multiple) end
 EOF
+pass;
index 3855afd3def169b24891b2a08090eba1fb40c6af..b23533ae938b3832767c721fbc8d7e523cc9165e 100644 (file)
@@ -16,3 +16,4 @@ check_expected ([<<'EOF']);
 (priority-donate-multiple2) Main thread should have priority 31.  Actual priority: 31.
 (priority-donate-multiple2) end
 EOF
+pass;
index 6ec1b4aca3a6d4a415ac156c6ae9ace619039de4..923460ed14a7d20ab84ffa2fdcd60bda110e7cc4 100644 (file)
@@ -16,3 +16,4 @@ check_expected ([<<'EOF']);
 (priority-donate-nest) Low thread should have priority 31.  Actual priority: 31.
 (priority-donate-nest) end
 EOF
+pass;
index c09ecfd8830103931d3915fa6e28b3a802ef1028..b7c8e6fe7f599bad767af5225748fd9baf7aca00 100644 (file)
@@ -14,3 +14,4 @@ check_expected ([<<'EOF']);
 (priority-donate-one) This should be the last line before finishing this test.
 (priority-donate-one) end
 EOF
+pass;
index 904dbc17b5f09e951d3094e2d27750f7cb146ad8..92b8d07d7b4fdfa38defe8790873711ffa4b4a04 100644 (file)
@@ -13,3 +13,4 @@ check_expected ([<<'EOF']);
 (priority-donate-sema) Main thread finished.
 (priority-donate-sema) end
 EOF
+pass;
index a5322ec7579f7dd33d4a48786d716297b2f9edd0..11f1dd3e31b305be45b61643a42a0d742abd688a 100644 (file)
@@ -29,7 +29,7 @@ use tests::tests;
 our ($test);
 my (@output) = read_text_file ("$test.output");
 
-common_checks (@output);
+common_checks ("run", @output);
 
 my ($thread_cnt) = 16;
 my ($iter_cnt) = 16;
index e41f3323f9902d317c48fda382cf91ed958df061..43a26ee66c3ac2e2277ae7faa1053b72e7ace63e 100644 (file)
@@ -13,3 +13,4 @@ check_expected ([<<'EOF']);
 (priority-preempt) The high-priority thread should have already completed.
 (priority-preempt) end
 EOF
+pass;
index f2b9cde9203c779a3468d268a16bcea72379f4c8..559988d7346abc29958909573a577611323f434f 100644 (file)
@@ -26,3 +26,4 @@ check_expected ([<<'EOF']);
 (priority-sema) Back in main thread.
 (priority-sema) end
 EOF
+pass;
index f8ad9c977d852cdfd548f8a9075ed7cc56d981ad..9a5869f51e8b32643f9f4bcd564ab55078ba2498 100644 (file)
@@ -1,8 +1,6 @@
 # -*- makefile -*-
 
-PINTOSFLAGS += --fs-disk=2
-KERNELFLAGS += -f
-
+tests/%.output: FSDISK = 2
 tests/%.output: PUTFILES = $(filter-out os.dsk, $^)
 
 tests/userprog_TESTS = $(addprefix tests/userprog/,args-none           \
index b0a32e02fe0ea48ede58f8ea499ea81f116b41f8..dfbcf4b878dc452455038e71a0406c8eac570a16 100644 (file)
@@ -12,3 +12,4 @@ check_expected ([<<'EOF']);
 (args) end
 args-dbl-space: exit(0)
 EOF
+pass;
index 3ed939fdc6f0afbf3f42dc72c96831d396dcbda8..214574a828a4c67a17f7d7b7996866325d08888c 100644 (file)
@@ -32,3 +32,4 @@ check_expected ([<<'EOF']);
 (args) end
 args-many: exit(0)
 EOF
+pass;
index 11596ff49b18122450acc29c3af9c8aab8add0f0..227e6cc97ffc8c0230cd748bd20fcc1a612e411a 100644 (file)
@@ -14,3 +14,4 @@ check_expected ([<<'EOF']);
 (args) end
 args-multiple: exit(0)
 EOF
+pass;
index 9679fa088119ca92ec9e40cf2f39a591116243a1..146318e0c330cf7e65cb1dede2462251b60c8d37 100644 (file)
@@ -10,3 +10,4 @@ check_expected ([<<'EOF']);
 (args) end
 args-none: exit(0)
 EOF
+pass;
index aeca3582b73a07f2afdfc963592ece8038524318..24582b4da4b7e8d8ca00968cbe4986c4fe21a0ad 100644 (file)
@@ -11,3 +11,4 @@ check_expected ([<<'EOF']);
 (args) end
 args-single: exit(0)
 EOF
+pass;
index 4a0be96fa0c5fed693c1c664b3297a039f51dff3..497b17c1156806128b59c8859b37168133210f2f 100644 (file)
@@ -10,3 +10,4 @@ EOF
 (close-bad-fd) begin
 close-bad-fd: exit(-1)
 EOF
+pass;
index 890cea0b434f1f95d82b12b45aaae1e1c4e36e22..fe4134287aa673826e87cb40807e2ad62d81bd0c 100644 (file)
@@ -9,3 +9,4 @@ check_expected ([<<'EOF']);
 (close-normal) end
 close-normal: exit(0)
 EOF
+pass;
index c62b53f3eb4968b0a6f4294b6831f1971e9a6f2e..3d285074f505fd82fe9a3028bc2f4e9c1883f267 100644 (file)
@@ -10,3 +10,4 @@ EOF
 (close-stdin) begin
 close-stdin: exit(-1)
 EOF
+pass;
index 83cf9840117ca7a468399a2e0c39c554770ee6c6..3cbbcff5c5407785be4ce34a89f0ff29709914c9 100644 (file)
@@ -10,3 +10,4 @@ EOF
 (close-stdout) begin
 close-stdout: exit(-1)
 EOF
+pass;
index e21b169c09bc8f0dab855710892679a3714224d3..deb55a6d3c613d6917808e9b4ec9d02020189fd1 100644 (file)
@@ -16,3 +16,4 @@ EOF
 (close-twice) close "sample.txt" again
 close-twice: exit(-1)
 EOF
+pass;
index 46453bb7e0238a2cee9fa6dd1b6c6db649b64040..ac134056634333f8ddd7d11274a17f7c91caf29b 100644 (file)
@@ -6,3 +6,4 @@ check_expected ([<<'EOF']);
 (create-bad-ptr) begin
 create-bad-ptr: exit(-1)
 EOF
+pass;
index 87b7bd5b35abf5ba4d222cb15e69a4fb65391a32..7656b7fe8e50d57b2637e02f5797683ae5660144 100644 (file)
@@ -8,3 +8,4 @@ check_expected ([<<'EOF']);
 (create-bound) end
 create-bound: exit(0)
 EOF
+pass;
index 32fcb009b456a4f4765d48bb8061e68cb066da86..93a10588453b20446e9a26eb8fc838e22791cf67 100644 (file)
@@ -11,3 +11,4 @@ EOF
 (create-empty) begin
 create-empty: exit(-1)
 EOF
+pass;
index d227033fdf86b54f8d017930eff06ffd1e9222d3..006885ef82e49efcc10a7147fece62dec86a882a 100644 (file)
@@ -12,3 +12,4 @@ check_expected ([<<'EOF']);
 (create-exists) end
 create-exists: exit(0)
 EOF
+pass;
index 312458424745dd279a9738a694396f8e3e71169a..628411cd53cd081460613fbfbbaa095e73366b1b 100644 (file)
@@ -8,3 +8,4 @@ check_expected ([<<'EOF']);
 (create-long) end
 create-long: exit(0)
 EOF
+pass;
index c956a1cf2e40df75c7b40ccc0172ec4e81685d53..ca74a6eac7a40514bafaaeb3048c9458ed24aa98 100644 (file)
@@ -8,3 +8,4 @@ check_expected ([<<'EOF']);
 (create-normal) end
 create-normal: exit(0)
 EOF
+pass;
index 641ff9b26de0621cbee22fcb1d0e9bdd6101e14b..09b7872aa67cf9cecfe9908eff7ed7a77cd53a77 100644 (file)
@@ -6,3 +6,4 @@ check_expected ([<<'EOF']);
 (create-null) begin
 create-null: exit(-1)
 EOF
+pass;
index bdedca650c117583e806c00ab68d8fbf95cc905d..b7533ed9d81499d33bf090c61dc75426ffc82266 100644 (file)
@@ -14,3 +14,4 @@ child-args: exit(0)
 (exec-arg) end
 exec-arg: exit(0)
 EOF
+pass;
index f0fdd69ec693d247ca19987287a0c6b12b61a950..63f5f78cc2d6be86d3fac76aa1d8f7fd6628f0d1 100644 (file)
@@ -10,3 +10,4 @@ EOF
 (exec-bad-ptr) begin
 exec-bad-ptr: exit(-1)
 EOF
+pass;
index 726a4e7a8b1a15a30e37dc77bbfff983b346e8a6..0ef7aaa76d4728a67ac571058ad33daad3466ac2 100644 (file)
@@ -28,3 +28,4 @@ no-such-file: exit(-1)
 (exec-missing) end
 exec-missing: exit(0)
 EOF
+pass;
index 60769587bb796ada51b289287159100748601cd1..99624cd7bd87174462fb6dc1635485e1b7b2557d 100644 (file)
@@ -15,3 +15,4 @@ child-simple: exit(81)
 (exec-multiple) end
 exec-multiple: exit(0)
 EOF
+pass;
index 7aa688a16f50d75d67f1819fa7dae92cc1db3ab4..00b59ededcc1fde171a5b58ed013ae5fd19ac4b4 100644 (file)
@@ -9,3 +9,4 @@ child-simple: exit(81)
 (exec-once) end
 exec-once: exit(0)
 EOF
+pass;
index 206c48b0b1f9cd233938d33789d830adfae6b22f..a552702b61a9a880471746dad64b17787b9b2941 100644 (file)
@@ -6,3 +6,4 @@ check_expected ([<<'EOF']);
 (exit) begin
 exit: exit(57)
 EOF
+pass;
index 4b1207d6b595084948f972dc43d86291e6d6ef15..1b701ed9076f8192e3e4e0247b2817ea10341dfb 100644 (file)
@@ -6,7 +6,7 @@ use tests::tests;
 our ($test);
 my (@output) = read_text_file ("$test.output");
 
-common_checks (@output);
+common_checks ("run", @output);
 
 fail "missing 'begin' message\n"
   if !grep ($_ eq '(halt) begin', @output);
index bad037834385f66b2ccbaae2031ce1fa610a9477..d0b3a33922258bb1c310294db3eba63d2bcedf9a 100644 (file)
@@ -22,3 +22,4 @@ child-close: exit(-1)
 (multi-child-fd) end
 multi-child-fd: exit(0)
 EOF
+pass;
index d2a4e1b206e7f11db9495cf6cb3791ae217eb245..41eb4a6e5a325e7b3da7a93b232399b9cca75ec3 100644 (file)
@@ -67,3 +67,4 @@ multi-recurse: exit(14)
 (multi-recurse) end 15
 multi-recurse: exit(15)
 EOF
+pass;
index 52434a230c68a2f187cd45641f94c8871dbb959a..7ed5cc86defbe41c3c2d5658269cd226097a9f7f 100644 (file)
@@ -5,9 +5,9 @@ use tests::tests;
 
 our ($test);
 my (@output) = read_text_file ("$test.output");
-common_checks (@output);
+common_checks ("run", @output);
 
-@output = get_core_output (@output);
+@output = get_core_output ("run", @output);
 my ($n) = 0;
 while (my ($m) = $output[0] =~ /^\(multi-oom\) begin (\d+)$/) {
     fail "Child process $m started out of order.\n" if $m != $n;
index cacc658947e591937a6765b52f641d12d19b50b8..980de35ca6cb582cd8f0cad26465569dd021e74c 100644 (file)
@@ -5,3 +5,4 @@ use tests::tests;
 check_expected ([<<'EOF']);
 system call!
 EOF
+pass;
index c0a1153ca3908914f4fb1e10759e2d0e3875fee3..45349e2c91537b8034c1089a6a721c3360867410 100644 (file)
@@ -10,3 +10,4 @@ EOF
 (open-bad-ptr) begin
 open-bad-ptr: exit(-1)
 EOF
+pass;
index 40c9bf61580acae4d5cbf29881cd4f73fbd9ca60..8060d223c2436831785a8591f8bb3dbc0a8540f1 100644 (file)
@@ -8,3 +8,4 @@ check_expected ([<<'EOF']);
 (open-boundary) end
 open-boundary: exit(0)
 EOF
+pass;
index 5537d257f7843c2627408bb760dc4ef17fcdd6b0..885fb415cd84fdb2adb69c60fa65c2b50124b11b 100644 (file)
@@ -7,3 +7,4 @@ check_expected ([<<'EOF']);
 (open-empty) end
 open-empty: exit(0)
 EOF
+pass;
index a1aaf79e38c2786f8f093cd2208404ba656b16c0..d72d87868c8e31edce579f852ee9de9999cbff4c 100644 (file)
@@ -7,3 +7,4 @@ check_expected ([<<'EOF']);
 (open-missing) end
 open-missing: exit(0)
 EOF
+pass;
index 492433fd73dde68ec9500db96e76050b92fe6850..4f6c34250f94d8bfa8ad92c83efba8b631fba460 100644 (file)
@@ -7,3 +7,4 @@ check_expected ([<<'EOF']);
 (open-normal) end
 open-normal: exit(0)
 EOF
+pass;
index 92188b3c544e9773ea57818c3357212a8e92d7be..b4a3bcb4853b0908a52e2db38bde5e41938fbf24 100644 (file)
@@ -10,3 +10,4 @@ EOF
 (open-null) begin
 open-null: exit(-1)
 EOF
+pass;
index d23ee844ad0b7bdf25bed02cb81002360d2f1161..64fa805b277434a2b7a48c5d6ffa73dad64f812d 100644 (file)
@@ -9,3 +9,4 @@ check_expected ([<<'EOF']);
 (open-twice) end
 open-twice: exit(0)
 EOF
+pass;
index 3dd5a93a92c33fb3f7121b147b36e52eb620d3e9..5fedcc7c7f6600ec87df48f65851c01322c31f50 100644 (file)
@@ -10,3 +10,4 @@ EOF
 (read-bad-fd) begin
 read-bad-fd: exit(-1)
 EOF
+pass;
index 2c95bc6e9cb7f13e547d010ba41288b9fd90c4c1..d10accfd599805b4e3768c0dc4d9df7ead3df416 100644 (file)
@@ -12,3 +12,4 @@ EOF
 (read-bad-ptr) open "sample.txt"
 read-bad-ptr: exit(-1)
 EOF
+pass;
index 505b24bc28eb1ce803457cca1cd4b2926b110147..08dc1612734966f0ad460ffb5a589e9e6aa8583c 100644 (file)
@@ -8,3 +8,4 @@ check_expected ([<<'EOF']);
 (read-boundary) end
 read-boundary: exit(0)
 EOF
+pass;
index b1139cfa453d9c5d264b576ab4637bf7326145bd..0ed299828315945e98eb39e3b4ca3525d4837e6b 100644 (file)
@@ -10,3 +10,4 @@ check_expected ([<<'EOF']);
 (read-normal) end
 read-normal: exit(0)
 EOF
+pass;
index 758a1c295291b5b281db74b237398900dc1e25af..7d87b52b316aaad180da2035679a3a466eacc3b4 100644 (file)
@@ -10,3 +10,4 @@ EOF
 (read-stdout) begin
 read-stdout: exit(-1)
 EOF
+pass;
index 3d9b091cda0f86975861f587bab6856b7d5d2ed5..8346dbc325a2d74887ab6837c294e024643bd928 100644 (file)
@@ -8,3 +8,4 @@ check_expected ([<<'EOF']);
 (read-zero) end
 read-zero: exit(0)
 EOF
+pass;
index 29945751fcee8cc0bb7ce17d94fd9a10189b3158..e6363fb6104437513ed564e13a0842ae2afabf1b 100644 (file)
@@ -17,3 +17,4 @@ child-rox: exit(12)
 (rox-child) end
 rox-child: exit(0)
 EOF
+pass;
index 704ccce56178ef6c2cfd4a7aec2b29624a1a14ad..14b27db7e1d2246ffd606c77db987e8e1de61532 100644 (file)
@@ -41,3 +41,4 @@ child-rox: exit(12)
 (rox-multichild) end
 rox-multichild: exit(0)
 EOF
+pass;
index 67c31162df68bba25d52c90241628b2d720a5a0c..c9dcc663743cb3b1635e6e9c6b6813ed55ae08bd 100644 (file)
@@ -10,3 +10,4 @@ check_expected ([<<'EOF']);
 (rox-simple) end
 rox-simple: exit(0)
 EOF
+pass;
index a255768af667dde04e3244f778d7d62a33c2f691..89811056338ef199208fbf48d5a3471f1cf64266 100644 (file)
@@ -6,3 +6,4 @@ check_expected ([<<'EOF']);
 (sc-bad-arg) begin
 sc-bad-arg: exit(-1)
 EOF
+pass;
index d0622d496ee895120cb024a96422c1904b31a009..498cec141f15846a071dd4fdf8b42eca3d91d32b 100644 (file)
@@ -6,3 +6,4 @@ check_expected ([<<'EOF']);
 (sc-bad-sp) begin
 sc-bad-sp: exit(-1)
 EOF
+pass;
index 61c9f230d3a4e017fddf843a80e16848ba439444..43766bf1b5ebfc0c67e4d8a0a45616e4568d81c5 100644 (file)
@@ -6,3 +6,4 @@ check_expected ([<<'EOF']);
 (sc-boundary-2) begin
 sc-boundary-2: exit(67)
 EOF
+pass;
index f00c3eb45e1ef08ea1b507c3b3c6b4b8bc58d960..3f7cbaf1ed41ad0df47d616e9d929562d3e8042d 100644 (file)
@@ -6,3 +6,4 @@ check_expected ([<<'EOF']);
 (sc-boundary) begin
 sc-boundary: exit(42)
 EOF
+pass;
index 3c36a5365aa5356c24fe120e908f05c5b080cc3d..db63fb990c0f921e9ae3ff8ab4accbefbfc0991c 100644 (file)
@@ -10,3 +10,4 @@ EOF
 (wait-bad-pid) begin
 wait-bad-pid: exit(-1)
 EOF
+pass;
index 6bc5c2096ccbc8ecdf1b161081f30d5a7a0aff8b..5df0e9c1330f5376e41241fe63a98692820d9bd2 100644 (file)
@@ -10,3 +10,4 @@ child-bad: exit(-1)
 (wait-killed) end
 wait-killed: exit(0)
 EOF
+pass;
index 8e53e8c211cb41d3cf0dc96e72109595cd94361d..93dd577667e053f61d10e6d48d0b8437da863256 100644 (file)
@@ -10,3 +10,4 @@ child-simple: exit(81)
 (wait-simple) end
 wait-simple: exit(0)
 EOF
+pass;
index e013123a13d6bf53893628a519c48aa56dc435cd..6d5384319a2c91078a397aa83fd8d1f0d75dcc9c 100644 (file)
@@ -11,3 +11,4 @@ child-simple: exit(81)
 (wait-twice) end
 wait-twice: exit(0)
 EOF
+pass;
index 23cee0665b7fb3053bba596bc733d2886eb3e032..8da7a8bbe79a5c1f0520ebc0d4c62318b70e73fa 100644 (file)
@@ -10,3 +10,4 @@ EOF
 (write-bad-fd) begin
 write-bad-fd: exit(-1)
 EOF
+pass;
index 84d3372b499160ed4cb5ef10d36e64a09bc54a00..ad9f399c81bb1c4d87306d2266ec555d96cfec45 100644 (file)
@@ -12,3 +12,4 @@ EOF
 (write-bad-ptr) open "sample.txt"
 write-bad-ptr: exit(-1)
 EOF
+pass;
index 720e3cd6b15efa06ea239c0b8d8d7f1b29f22b5b..788378179c57064823ab362c2176edafdc1b3c3f 100644 (file)
@@ -8,3 +8,4 @@ check_expected ([<<'EOF']);
 (write-boundary) end
 write-boundary: exit(0)
 EOF
+pass;
index c78cfb570e7af838a217ec23f4189b4edd4eb00f..9fa6024c09a679df06bcef847f2132fc07e39c35 100644 (file)
@@ -9,3 +9,4 @@ check_expected ([<<'EOF']);
 (write-normal) end
 write-normal: exit(0)
 EOF
+pass;
index 3aca818ae20219997c7051fb26e5783a247c703f..a6caf81edd6a213c5bd97c907247d2954865d50d 100644 (file)
@@ -10,3 +10,4 @@ EOF
 (write-stdin) begin
 write-stdin: exit(-1)
 EOF
+pass;
index 5fe4385400b5a0a6b0c51f3d3f0b9a0b57e09464..cc4cd609f4e402ad5fa77e19c438a0edde02bcd6 100644 (file)
@@ -8,3 +8,4 @@ check_expected ([<<'EOF']);
 (write-zero) end
 write-zero: exit(0)
 EOF
+pass;
index 4a5820d81ed3d75a2330c2b4778220a838c6c4bb..460bfd0706cf60b3bcf41cf4a6be051671998a41 100644 (file)
@@ -1,7 +1,5 @@
 # -*- makefile -*-
 
-PINTOSFLAGS += --swap-disk=4
-
 tests/vm_TESTS = $(addprefix tests/vm/,pt-grow-stack pt-grow-pusha     \
 pt-grow-bad pt-big-stk-obj pt-bad-addr pt-bad-read pt-write-code       \
 pt-write-code2 pt-grow-stk-sc page-linear page-parallel page-merge-seq \
index 2873af1f804061efcd75dc137cfa1ad18206f4ec..f3f58d577994d2a05bda9396eae9df81d4cd110f 100644 (file)
@@ -12,3 +12,4 @@ EOF
 (mmap-bad-fd) try to mmap invalid fd
 mmap-bad-fd: exit(-1)
 EOF
+pass;
index 29e44aacd3cfdc2e90725430d52a7f6aabd02401..1666d6cd469b93d1190681cae13bd8b51f24a221 100644 (file)
@@ -13,3 +13,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (mmap-clean) file change was retained after munmap
 (mmap-clean) end
 EOF
+pass;
index 6c7a1992a588fa5d8aaa3347007b12cfe7e6a49c..d15e41ae7ba255217ed947ccf95f87d4693456ff 100644 (file)
@@ -8,3 +8,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (mmap-close) mmap "sample.txt"
 (mmap-close) end
 EOF
+pass;
index 7f117427854d7a82ee5e57af5f89305e37518e69..457d34a029b8854a31690d9b12000ad09b2f71e4 100644 (file)
@@ -14,3 +14,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (mmap-exit) close "sample.txt"
 (mmap-exit) end
 EOF
+pass;
index 59b53897faa4c62bcf1a582eef24e4cc065bb972..7e69122ca559f1ba00787cb6c9a360607c1f9a94 100644 (file)
@@ -13,3 +13,4 @@ child-inherit: exit(-1)
 (mmap-inherit) end
 mmap-inherit: exit(0)
 EOF
+pass;
index fc1234dde0e860b9bdf0c7c2d9c8675cc8a1ba8f..145a2e895db69ce129677e816156d620af54189c 100644 (file)
@@ -8,3 +8,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (mmap-misalign) try to mmap at misaligned address
 (mmap-misalign) end
 EOF
+pass;
index 7cfc1f188f95939620b6f11033b463c37c36739d..aacdd65f524be22822f80dd485e9879984303faf 100644 (file)
@@ -8,3 +8,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (mmap-null) try to mmap at address 0
 (mmap-null) end
 EOF
+pass;
index bb8cb2dae1632d03de32d4702ac05bb1166e86e4..b5b23c7b9930f458cff3ae209e64bd41d46c7499 100644 (file)
@@ -8,3 +8,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (mmap-over-code) try to mmap over code segment
 (mmap-over-code) end
 EOF
+pass;
index 15a4f6d48ecec07b9ef9066f2e2d182407af01ec..98770cccf6e66faa49d2e4c73bc7ad5ac152a8b5 100644 (file)
@@ -8,3 +8,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (mmap-over-data) try to mmap over data segment
 (mmap-over-data) end
 EOF
+pass;
index 3b7ac98c6fdf573af904ca20f9ddbe71bf083428..e6880cfbe58497e8020edfc595598176efd6e0a7 100644 (file)
@@ -8,3 +8,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (mmap-over-stk) try to mmap over stack segment
 (mmap-over-stk) end
 EOF
+pass;
index f8b58ab7e419caa5b3f73e422bd024f780d4d00e..f13801e7a806226ce90d88bb3bd8926591c9ef57 100644 (file)
@@ -10,3 +10,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (mmap-overlap) try to mmap "zeros" again
 (mmap-overlap) end
 EOF
+pass;
index 9978310a51d4bc0ee0f7adbad2bac5fef31352ef..95ab7901abfe297f10b9c5eb6f67a6525bad05f9 100644 (file)
@@ -8,3 +8,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (mmap-read) mmap "sample.txt"
 (mmap-read) end
 EOF
+pass;
index 1b8a311dc5448e578ec7d1b90dea7e5d3edd1750..d3cc93847d0e0a64b0214d4ac47c5968361600fe 100644 (file)
@@ -11,3 +11,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (mmap-remove) create "another"
 (mmap-remove) end
 EOF
+pass;
index fcfa0b2182926c9861b23c652663ed2cb0441fd7..c15830170311a2dc78429351b2f1ef963b30a74e 100644 (file)
@@ -44,3 +44,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<EOF]);
 (mmap-shuffle) shuffle 9: cksum=$shuffle[9]
 (mmap-shuffle) end
 EOF
+pass;
index 8fde8dfcf7e9633ee62106955736d60f8b037838..05e972459e7e83c9eea89a9c81153200a303873f 100644 (file)
@@ -12,3 +12,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (mmap-twice) compare mmap'd file 1 against data
 (mmap-twice) end
 EOF
+pass;
index d48ce3a549a6cb8998a29617ce1ac4dac62623c2..d2c9cc511f43da3eb8f0910477925757310efd6d 100644 (file)
@@ -10,3 +10,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (mmap-write) compare read data against written data
 (mmap-write) end
 EOF
+pass;
index 1625798127e869526daf6bbd4d8555c576bc387b..0130fbd2e0f2cc61df3fb31f35786457c4befe34 100644 (file)
@@ -9,3 +9,4 @@ check_expected ([<<'EOF']);
 (mmap-zero) mmap "empty"
 mmap-zero: exit(-1)
 EOF
+pass;
index c4a26c80a9d43c5870bc00a42f73b2bf04bfa8bb..dcbc8843efa2571e63f99a7c9530b004010d2e4c 100644 (file)
@@ -11,3 +11,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (page-linear) read pass
 (page-linear) end
 EOF
+pass;
index 9f6205a550bd9227e4f672f38bb43d4bf9f7cbcf..31f8aa7dc3f7cb3b02fa6ed40336f6de25c074fb 100644 (file)
@@ -26,3 +26,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (page-merge-par) success, buf_idx=1,048,576
 (page-merge-par) end
 EOF
+pass;
index 7bfe2759cbefe18164ac050a70c3bba06dad1569..d78f69da534a19813ba9d7bb3ab28b6095f3563f 100644 (file)
@@ -26,3 +26,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (page-merge-seq) success, buf_idx=1,032,192
 (page-merge-seq) end
 EOF
+pass;
index 14b37df54df40d5c78cb59df35a7e103add4302d..c6817b7657c1f5f95d3fe55176c3adca51ed2d9c 100644 (file)
@@ -12,3 +12,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (page-parallel) wait for child 2
 (page-parallel) end
 EOF
+pass;
index 88ec934bb0303ef74e864a2addfd3b595f7cf3a7..6447d380eba51719547768c6702835e383d80340 100644 (file)
@@ -41,3 +41,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<EOF]);
 (page-shuffle) shuffle 9: cksum=$shuffle[9]
 (page-shuffle) end
 EOF
+pass;
index b9a194b8efb2b1f2733dd4824b2f5d9a45b69e96..52039a1a1986939c52e074d2faf8d200bef508ac 100644 (file)
@@ -8,8 +8,8 @@ sub check_process_death {
     our ($test);
     my (@output) = read_text_file ("$test.output");
 
-    common_checks (@output);
-    @output = get_core_output (@output);
+    common_checks ("run", @output);
+    @output = get_core_output ("run", @output);
     fail "First line of output is not `($proc_name) begin' message.\n"
       if $output[0] ne "($proc_name) begin";
     fail "Output missing '$proc_name: exit(-1)' message.\n"
index 35543fefb55ba59944c1a2abf278aec0b6f4717b..1f96bb445d8869b5976b7a75f248476ee308ea20 100644 (file)
@@ -7,3 +7,4 @@ check_expected ([<<'EOF']);
 (pt-bad-read) open "sample.txt"
 pt-bad-read: exit(-1)
 EOF
+pass;
index bfaa59aa59d8f8fcc6c8fecc64502e0f748ced36..eb5853a23576ba65428d10251331c5672ac0dd2e 100644 (file)
@@ -7,3 +7,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (pt-big-stk-obj) cksum: 3256410166
 (pt-big-stk-obj) end
 EOF
+pass;
index cc3d31e72b7e21359f9337e7552ed26d05f7d4fc..a5775c77424b9de76e9290041d0569067ba627e8 100644 (file)
@@ -6,3 +6,4 @@ check_expected ([<<'EOF']);
 (pt-grow-bad) begin
 pt-grow-bad: exit(-1)
 EOF
+pass;
index 86538882511856a88b1079ee2f9970e49b1698fa..5000966ed473eaaad125bc8879f4e47202b71414 100644 (file)
@@ -6,3 +6,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (pt-grow-pusha) begin
 (pt-grow-pusha) end
 EOF
+pass;
index 92d8f9372d7ca736e4413f59b35f461257abb1e6..1e669db94c360f64295857ad83f6d04e24122b2c 100644 (file)
@@ -7,3 +7,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (pt-grow-stack) cksum: 3424492700
 (pt-grow-stack) end
 EOF
+pass;
index 005f6f457f4f0162786bdb470649dcc87009954b..23d3b02e8af0d6d6cc6b7a8fc149b43a1c7c14a1 100644 (file)
@@ -12,3 +12,4 @@ check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
 (pt-grow-stk-sc) compare written data against read data
 (pt-grow-stk-sc) end
 EOF
+pass;
index ac8ff2aa67a93fb150712a3727e25ad0311d4264..69ffc77ca4b3a7960adcdb91b66da10b0bb4fd96 100644 (file)
@@ -7,3 +7,4 @@ check_expected ([<<'EOF']);
 (pt-write-code2) open "sample.txt"
 pt-write-code2: exit(-1)
 EOF
+pass;
index 102e1e96f21f92a17002abc004ef1654eb7476ec..f8cd3579f69aad5289f9d69fa9ec96e3076c0f29 100644 (file)
@@ -19,7 +19,7 @@ cd $@/src && $(MAKE) -s clean
 endef
 
 define run-tests
-cd $@/src/$(PROJECT) && $(MAKE) check
+cd $@/src/$(PROJECT) && time $(MAKE) check
 endef
 
 define grade-tests