summaryrefslogtreecommitdiffstats
path: root/tests/filesys/extended
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2012-03-27 11:51:08 +0200
committermanuel <manuel@mausz.at>2012-03-27 11:51:08 +0200
commit4f670845ff9ab6c48bcb5f7bf4d4ef6dc3c3064b (patch)
tree868c52e06f207b5ec8a3cc141f4b8b2bdfcc165c /tests/filesys/extended
parenteae0bd57f0a26314a94785061888d193d186944a (diff)
downloadprogos-4f670845ff9ab6c48bcb5f7bf4d4ef6dc3c3064b.tar.gz
progos-4f670845ff9ab6c48bcb5f7bf4d4ef6dc3c3064b.tar.bz2
progos-4f670845ff9ab6c48bcb5f7bf4d4ef6dc3c3064b.zip
reorganize file structure to match the upstream requirements
Diffstat (limited to 'tests/filesys/extended')
-rw-r--r--tests/filesys/extended/Make.tests61
-rw-r--r--tests/filesys/extended/Rubric.functionality26
-rw-r--r--tests/filesys/extended/Rubric.persistence24
-rw-r--r--tests/filesys/extended/Rubric.robustness9
-rw-r--r--tests/filesys/extended/child-syn-rw.c53
-rw-r--r--tests/filesys/extended/dir-empty-name-persistence.ck6
-rw-r--r--tests/filesys/extended/dir-empty-name.c12
-rw-r--r--tests/filesys/extended/dir-empty-name.ck10
-rw-r--r--tests/filesys/extended/dir-mk-tree-persistence.ck16
-rw-r--r--tests/filesys/extended/dir-mk-tree.c12
-rw-r--r--tests/filesys/extended/dir-mk-tree.ck12
-rw-r--r--tests/filesys/extended/dir-mkdir-persistence.ck6
-rw-r--r--tests/filesys/extended/dir-mkdir.c15
-rw-r--r--tests/filesys/extended/dir-mkdir.ck13
-rw-r--r--tests/filesys/extended/dir-open-persistence.ck6
-rw-r--r--tests/filesys/extended/dir-open.c21
-rw-r--r--tests/filesys/extended/dir-open.ck20
-rw-r--r--tests/filesys/extended/dir-over-file-persistence.ck6
-rw-r--r--tests/filesys/extended/dir-over-file.c13
-rw-r--r--tests/filesys/extended/dir-over-file.ck11
-rw-r--r--tests/filesys/extended/dir-rm-cwd-persistence.ck8
-rw-r--r--tests/filesys/extended/dir-rm-cwd.c75
-rw-r--r--tests/filesys/extended/dir-rm-cwd.ck51
-rw-r--r--tests/filesys/extended/dir-rm-parent-persistence.ck6
-rw-r--r--tests/filesys/extended/dir-rm-parent.c16
-rw-r--r--tests/filesys/extended/dir-rm-parent.ck14
-rw-r--r--tests/filesys/extended/dir-rm-root-persistence.ck6
-rw-r--r--tests/filesys/extended/dir-rm-root.c13
-rw-r--r--tests/filesys/extended/dir-rm-root.ck11
-rw-r--r--tests/filesys/extended/dir-rm-tree-persistence.ck6
-rw-r--r--tests/filesys/extended/dir-rm-tree.c62
-rw-r--r--tests/filesys/extended/dir-rm-tree.ck14
-rw-r--r--tests/filesys/extended/dir-rmdir-persistence.ck6
-rw-r--r--tests/filesys/extended/dir-rmdir.c14
-rw-r--r--tests/filesys/extended/dir-rmdir.ck12
-rw-r--r--tests/filesys/extended/dir-under-file-persistence.ck6
-rw-r--r--tests/filesys/extended/dir-under-file.c13
-rw-r--r--tests/filesys/extended/dir-under-file.ck11
-rw-r--r--tests/filesys/extended/dir-vine-persistence.ck37
-rw-r--r--tests/filesys/extended/dir-vine.c85
-rw-r--r--tests/filesys/extended/dir-vine.ck11
-rw-r--r--tests/filesys/extended/grow-create-persistence.ck6
-rw-r--r--tests/filesys/extended/grow-create.c4
-rw-r--r--tests/filesys/extended/grow-create.ck13
-rw-r--r--tests/filesys/extended/grow-dir-lg-persistence.ck9
-rw-r--r--tests/filesys/extended/grow-dir-lg.c6
-rw-r--r--tests/filesys/extended/grow-dir-lg.ck61
-rw-r--r--tests/filesys/extended/grow-dir.inc41
-rw-r--r--tests/filesys/extended/grow-file-size-persistence.ck7
-rw-r--r--tests/filesys/extended/grow-file-size.c33
-rw-r--r--tests/filesys/extended/grow-file-size.ck17
-rw-r--r--tests/filesys/extended/grow-root-lg-persistence.ck9
-rw-r--r--tests/filesys/extended/grow-root-lg.c4
-rw-r--r--tests/filesys/extended/grow-root-lg.ck60
-rw-r--r--tests/filesys/extended/grow-root-sm-persistence.ck9
-rw-r--r--tests/filesys/extended/grow-root-sm.c4
-rw-r--r--tests/filesys/extended/grow-root-sm.ck30
-rw-r--r--tests/filesys/extended/grow-seq-lg-persistence.ck7
-rw-r--r--tests/filesys/extended/grow-seq-lg.c5
-rw-r--r--tests/filesys/extended/grow-seq-lg.ck17
-rw-r--r--tests/filesys/extended/grow-seq-sm-persistence.ck7
-rw-r--r--tests/filesys/extended/grow-seq-sm.c5
-rw-r--r--tests/filesys/extended/grow-seq-sm.ck17
-rw-r--r--tests/filesys/extended/grow-seq.inc20
-rw-r--r--tests/filesys/extended/grow-sparse-persistence.ck6
-rw-r--r--tests/filesys/extended/grow-sparse.c25
-rw-r--r--tests/filesys/extended/grow-sparse.ck17
-rw-r--r--tests/filesys/extended/grow-tell-persistence.ck7
-rw-r--r--tests/filesys/extended/grow-tell.c32
-rw-r--r--tests/filesys/extended/grow-tell.ck17
-rw-r--r--tests/filesys/extended/grow-two-files-persistence.ck9
-rw-r--r--tests/filesys/extended/grow-two-files.c62
-rw-r--r--tests/filesys/extended/grow-two-files.ck23
-rw-r--r--tests/filesys/extended/mk-tree.c67
-rw-r--r--tests/filesys/extended/mk-tree.h6
-rw-r--r--tests/filesys/extended/syn-rw-persistence.ck8
-rw-r--r--tests/filesys/extended/syn-rw.c35
-rw-r--r--tests/filesys/extended/syn-rw.ck20
-rw-r--r--tests/filesys/extended/syn-rw.h9
-rw-r--r--tests/filesys/extended/tar.c208
80 files changed, 1771 insertions, 0 deletions
diff --git a/tests/filesys/extended/Make.tests b/tests/filesys/extended/Make.tests
new file mode 100644
index 0000000..e03b98d
--- /dev/null
+++ b/tests/filesys/extended/Make.tests
@@ -0,0 +1,61 @@
1# -*- makefile -*-
2
3raw_tests = dir-empty-name dir-mk-tree dir-mkdir dir-open \
4dir-over-file dir-rm-cwd dir-rm-parent dir-rm-root dir-rm-tree \
5dir-rmdir dir-under-file dir-vine grow-create grow-dir-lg \
6grow-file-size grow-root-lg grow-root-sm grow-seq-lg grow-seq-sm \
7grow-sparse grow-tell grow-two-files syn-rw
8
9tests/filesys/extended_TESTS = $(patsubst %,tests/filesys/extended/%,$(raw_tests))
10tests/filesys/extended_EXTRA_GRADES = $(patsubst %,tests/filesys/extended/%-persistence,$(raw_tests))
11
12tests/filesys/extended_PROGS = $(tests/filesys/extended_TESTS) \
13tests/filesys/extended/child-syn-rw tests/filesys/extended/tar
14
15$(foreach prog,$(tests/filesys/extended_PROGS), \
16 $(eval $(prog)_SRC += $(prog).c tests/lib.c tests/filesys/seq-test.c))
17$(foreach prog,$(tests/filesys/extended_TESTS), \
18 $(eval $(prog)_SRC += tests/main.c))
19$(foreach prog,$(tests/filesys/extended_TESTS), \
20 $(eval $(prog)_PUTFILES += tests/filesys/extended/tar))
21# The version of GNU make 3.80 on vine barfs if this is split at
22# the last comma.
23$(foreach test,$(tests/filesys/extended_TESTS),$(eval $(test).output: FILESYSSOURCE = --disk=tmp.dsk))
24
25tests/filesys/extended/dir-mk-tree_SRC += tests/filesys/extended/mk-tree.c
26tests/filesys/extended/dir-rm-tree_SRC += tests/filesys/extended/mk-tree.c
27
28tests/filesys/extended/syn-rw_PUTFILES += tests/filesys/extended/child-syn-rw
29
30tests/filesys/extended/dir-vine.output: TIMEOUT = 150
31
32GETTIMEOUT = 60
33
34GETCMD = pintos -v -k -T $(GETTIMEOUT)
35GETCMD += $(PINTOSOPTS)
36GETCMD += $(SIMULATOR)
37GETCMD += $(FILESYSSOURCE)
38GETCMD += -g fs.tar -a $(TEST).tar
39ifeq ($(filter vm, $(KERNEL_SUBDIRS)), vm)
40GETCMD += --swap-size=4
41endif
42GETCMD += -- -q
43GETCMD += $(KERNELFLAGS)
44GETCMD += run 'tar fs.tar /'
45GETCMD += < /dev/null
46GETCMD += 2> $(TEST)-persistence.errors $(if $(VERBOSE),|tee,>) $(TEST)-persistence.output
47
48tests/filesys/extended/%.output: kernel.bin
49 rm -f tmp.dsk
50 pintos-mkdisk tmp.dsk --filesys-size=2
51 $(TESTCMD)
52 $(GETCMD)
53 rm -f tmp.dsk
54$(foreach raw_test,$(raw_tests),$(eval tests/filesys/extended/$(raw_test)-persistence.output: tests/filesys/extended/$(raw_test).output))
55$(foreach raw_test,$(raw_tests),$(eval tests/filesys/extended/$(raw_test)-persistence.result: tests/filesys/extended/$(raw_test).result))
56
57TARS = $(addsuffix .tar,$(tests/filesys/extended_TESTS))
58
59clean::
60 rm -f $(TARS)
61 rm -f tests/filesys/extended/can-rmdir-cwd
diff --git a/tests/filesys/extended/Rubric.functionality b/tests/filesys/extended/Rubric.functionality
new file mode 100644
index 0000000..91ed6f0
--- /dev/null
+++ b/tests/filesys/extended/Rubric.functionality
@@ -0,0 +1,26 @@
1Functionality of extended file system:
2- Test directory support.
31 dir-mkdir
43 dir-mk-tree
5
61 dir-rmdir
73 dir-rm-tree
8
95 dir-vine
10
11- Test file growth.
121 grow-create
131 grow-seq-sm
143 grow-seq-lg
153 grow-sparse
163 grow-two-files
171 grow-tell
181 grow-file-size
19
20- Test directory growth.
211 grow-dir-lg
221 grow-root-sm
231 grow-root-lg
24
25- Test writing from multiple processes.
265 syn-rw
diff --git a/tests/filesys/extended/Rubric.persistence b/tests/filesys/extended/Rubric.persistence
new file mode 100644
index 0000000..405620a
--- /dev/null
+++ b/tests/filesys/extended/Rubric.persistence
@@ -0,0 +1,24 @@
1Persistence of file system:
21 dir-empty-name-persistence
31 dir-mk-tree-persistence
41 dir-mkdir-persistence
51 dir-open-persistence
61 dir-over-file-persistence
71 dir-rm-cwd-persistence
81 dir-rm-parent-persistence
91 dir-rm-root-persistence
101 dir-rm-tree-persistence
111 dir-rmdir-persistence
121 dir-under-file-persistence
131 dir-vine-persistence
141 grow-create-persistence
151 grow-dir-lg-persistence
161 grow-file-size-persistence
171 grow-root-lg-persistence
181 grow-root-sm-persistence
191 grow-seq-lg-persistence
201 grow-seq-sm-persistence
211 grow-sparse-persistence
221 grow-tell-persistence
231 grow-two-files-persistence
241 syn-rw-persistence
diff --git a/tests/filesys/extended/Rubric.robustness b/tests/filesys/extended/Rubric.robustness
new file mode 100644
index 0000000..fb9f32f
--- /dev/null
+++ b/tests/filesys/extended/Rubric.robustness
@@ -0,0 +1,9 @@
1Robustness of file system:
21 dir-empty-name
31 dir-open
41 dir-over-file
51 dir-under-file
6
73 dir-rm-cwd
82 dir-rm-parent
91 dir-rm-root
diff --git a/tests/filesys/extended/child-syn-rw.c b/tests/filesys/extended/child-syn-rw.c
new file mode 100644
index 0000000..0e2217d
--- /dev/null
+++ b/tests/filesys/extended/child-syn-rw.c
@@ -0,0 +1,53 @@
1/* Child process for syn-rw.
2 Reads from a file created by our parent process, which is
3 growing it. We loop until we've read the whole file
4 successfully. Many iterations through the loop will return 0
5 bytes, because the file has not grown in the meantime. That
6 is, we are "busy waiting" for the file to grow.
7 (This test could be improved by adding a "yield" system call
8 and calling yield whenever we receive a 0-byte read.) */
9
10#include <random.h>
11#include <stdlib.h>
12#include <syscall.h>
13#include "tests/filesys/extended/syn-rw.h"
14#include "tests/lib.h"
15
16const char *test_name = "child-syn-rw";
17
18static char buf1[BUF_SIZE];
19static char buf2[BUF_SIZE];
20
21int
22main (int argc, const char *argv[])
23{
24 int child_idx;
25 int fd;
26 size_t ofs;
27
28 quiet = true;
29
30 CHECK (argc == 2, "argc must be 2, actually %d", argc);
31 child_idx = atoi (argv[1]);
32
33 random_init (0);
34 random_bytes (buf1, sizeof buf1);
35
36 CHECK ((fd = open (file_name)) > 1, "open \"%s\"", file_name);
37 ofs = 0;
38 while (ofs < sizeof buf2)
39 {
40 int bytes_read = read (fd, buf2 + ofs, sizeof buf2 - ofs);
41 CHECK (bytes_read >= -1 && bytes_read <= (int) (sizeof buf2 - ofs),
42 "%zu-byte read on \"%s\" returned invalid value of %d",
43 sizeof buf2 - ofs, file_name, bytes_read);
44 if (bytes_read > 0)
45 {
46 compare_bytes (buf2 + ofs, buf1 + ofs, bytes_read, ofs, file_name);
47 ofs += bytes_read;
48 }
49 }
50 close (fd);
51
52 return child_idx;
53}
diff --git a/tests/filesys/extended/dir-empty-name-persistence.ck b/tests/filesys/extended/dir-empty-name-persistence.ck
new file mode 100644
index 0000000..562c451
--- /dev/null
+++ b/tests/filesys/extended/dir-empty-name-persistence.ck
@@ -0,0 +1,6 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_archive ({});
6pass;
diff --git a/tests/filesys/extended/dir-empty-name.c b/tests/filesys/extended/dir-empty-name.c
new file mode 100644
index 0000000..c4859d2
--- /dev/null
+++ b/tests/filesys/extended/dir-empty-name.c
@@ -0,0 +1,12 @@
1/* Tries to create a directory named as the empty string,
2 which must return failure. */
3
4#include <syscall.h>
5#include "tests/lib.h"
6#include "tests/main.h"
7
8void
9test_main (void)
10{
11 CHECK (!mkdir (""), "mkdir \"\" (must return false)");
12}
diff --git a/tests/filesys/extended/dir-empty-name.ck b/tests/filesys/extended/dir-empty-name.ck
new file mode 100644
index 0000000..d6c5621
--- /dev/null
+++ b/tests/filesys/extended/dir-empty-name.ck
@@ -0,0 +1,10 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(dir-empty-name) begin
7(dir-empty-name) mkdir "" (must return false)
8(dir-empty-name) end
9EOF
10pass;
diff --git a/tests/filesys/extended/dir-mk-tree-persistence.ck b/tests/filesys/extended/dir-mk-tree-persistence.ck
new file mode 100644
index 0000000..fb16afd
--- /dev/null
+++ b/tests/filesys/extended/dir-mk-tree-persistence.ck
@@ -0,0 +1,16 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5my ($tree);
6for my $a (0...3) {
7 for my $b (0...2) {
8 for my $c (0...2) {
9 for my $d (0...3) {
10 $tree->{$a}{$b}{$c}{$d} = [''];
11 }
12 }
13 }
14}
15check_archive ($tree);
16pass;
diff --git a/tests/filesys/extended/dir-mk-tree.c b/tests/filesys/extended/dir-mk-tree.c
new file mode 100644
index 0000000..a714ff3
--- /dev/null
+++ b/tests/filesys/extended/dir-mk-tree.c
@@ -0,0 +1,12 @@
1/* Creates directories /0/0/0 through /3/2/2 and creates files in
2 the leaf directories. */
3
4#include "tests/filesys/extended/mk-tree.h"
5#include "tests/main.h"
6
7void
8test_main (void)
9{
10 make_tree (4, 3, 3, 4);
11}
12
diff --git a/tests/filesys/extended/dir-mk-tree.ck b/tests/filesys/extended/dir-mk-tree.ck
new file mode 100644
index 0000000..a8507e2
--- /dev/null
+++ b/tests/filesys/extended/dir-mk-tree.ck
@@ -0,0 +1,12 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(dir-mk-tree) begin
7(dir-mk-tree) creating /0/0/0/0 through /3/2/2/3...
8(dir-mk-tree) open "/0/2/0/3"
9(dir-mk-tree) close "/0/2/0/3"
10(dir-mk-tree) end
11EOF
12pass;
diff --git a/tests/filesys/extended/dir-mkdir-persistence.ck b/tests/filesys/extended/dir-mkdir-persistence.ck
new file mode 100644
index 0000000..7682900
--- /dev/null
+++ b/tests/filesys/extended/dir-mkdir-persistence.ck
@@ -0,0 +1,6 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_archive ({'a' => {'b' => ["\0" x 512]}});
6pass;
diff --git a/tests/filesys/extended/dir-mkdir.c b/tests/filesys/extended/dir-mkdir.c
new file mode 100644
index 0000000..994f41c
--- /dev/null
+++ b/tests/filesys/extended/dir-mkdir.c
@@ -0,0 +1,15 @@
1/* Tests mkdir(). */
2
3#include <syscall.h>
4#include "tests/lib.h"
5#include "tests/main.h"
6
7void
8test_main (void)
9{
10 CHECK (mkdir ("a"), "mkdir \"a\"");
11 CHECK (create ("a/b", 512), "create \"a/b\"");
12 CHECK (chdir ("a"), "chdir \"a\"");
13 CHECK (open ("b") > 1, "open \"b\"");
14}
15
diff --git a/tests/filesys/extended/dir-mkdir.ck b/tests/filesys/extended/dir-mkdir.ck
new file mode 100644
index 0000000..4644f80
--- /dev/null
+++ b/tests/filesys/extended/dir-mkdir.ck
@@ -0,0 +1,13 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(dir-mkdir) begin
7(dir-mkdir) mkdir "a"
8(dir-mkdir) create "a/b"
9(dir-mkdir) chdir "a"
10(dir-mkdir) open "b"
11(dir-mkdir) end
12EOF
13pass;
diff --git a/tests/filesys/extended/dir-open-persistence.ck b/tests/filesys/extended/dir-open-persistence.ck
new file mode 100644
index 0000000..26ff2f1
--- /dev/null
+++ b/tests/filesys/extended/dir-open-persistence.ck
@@ -0,0 +1,6 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_archive ({"xyzzy" => {}});
6pass;
diff --git a/tests/filesys/extended/dir-open.c b/tests/filesys/extended/dir-open.c
new file mode 100644
index 0000000..29d18b8
--- /dev/null
+++ b/tests/filesys/extended/dir-open.c
@@ -0,0 +1,21 @@
1/* Opens a directory, then tries to write to it, which must
2 fail. */
3
4#include <syscall.h>
5#include "tests/lib.h"
6#include "tests/main.h"
7
8void
9test_main (void)
10{
11 int fd;
12 int retval;
13
14 CHECK (mkdir ("xyzzy"), "mkdir \"xyzzy\"");
15 CHECK ((fd = open ("xyzzy")) > 1, "open \"xyzzy\"");
16
17 msg ("write \"xyzzy\"");
18 retval = write (fd, "foobar", 6);
19 CHECK (retval == -1,
20 "write \"xyzzy\" (must return -1, actually %d)", retval);
21}
diff --git a/tests/filesys/extended/dir-open.ck b/tests/filesys/extended/dir-open.ck
new file mode 100644
index 0000000..fccc563
--- /dev/null
+++ b/tests/filesys/extended/dir-open.ck
@@ -0,0 +1,20 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected ([<<'EOF', <<'EOF']);
6(dir-open) begin
7(dir-open) mkdir "xyzzy"
8(dir-open) open "xyzzy"
9(dir-open) write "xyzzy"
10(dir-open) write "xyzzy" (must return -1, actually -1)
11(dir-open) end
12dir-open: exit(0)
13EOF
14(dir-open) begin
15(dir-open) mkdir "xyzzy"
16(dir-open) open "xyzzy"
17(dir-open) write "xyzzy"
18dir-open: exit(-1)
19EOF
20pass;
diff --git a/tests/filesys/extended/dir-over-file-persistence.ck b/tests/filesys/extended/dir-over-file-persistence.ck
new file mode 100644
index 0000000..56b4ed2
--- /dev/null
+++ b/tests/filesys/extended/dir-over-file-persistence.ck
@@ -0,0 +1,6 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_archive ({"abc" => {}});
6pass;
diff --git a/tests/filesys/extended/dir-over-file.c b/tests/filesys/extended/dir-over-file.c
new file mode 100644
index 0000000..cdd2c62
--- /dev/null
+++ b/tests/filesys/extended/dir-over-file.c
@@ -0,0 +1,13 @@
1/* Tries to create a file with the same name as an existing
2 directory, which must return failure. */
3
4#include <syscall.h>
5#include "tests/lib.h"
6#include "tests/main.h"
7
8void
9test_main (void)
10{
11 CHECK (mkdir ("abc"), "mkdir \"abc\"");
12 CHECK (!create ("abc", 0), "create \"abc\" (must return false)");
13}
diff --git a/tests/filesys/extended/dir-over-file.ck b/tests/filesys/extended/dir-over-file.ck
new file mode 100644
index 0000000..aae1c1e
--- /dev/null
+++ b/tests/filesys/extended/dir-over-file.ck
@@ -0,0 +1,11 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(dir-over-file) begin
7(dir-over-file) mkdir "abc"
8(dir-over-file) create "abc" (must return false)
9(dir-over-file) end
10EOF
11pass;
diff --git a/tests/filesys/extended/dir-rm-cwd-persistence.ck b/tests/filesys/extended/dir-rm-cwd-persistence.ck
new file mode 100644
index 0000000..7533570
--- /dev/null
+++ b/tests/filesys/extended/dir-rm-cwd-persistence.ck
@@ -0,0 +1,8 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5my ($cwd_removable) = read_text_file ("tests/filesys/extended/can-rmdir-cwd");
6$cwd_removable eq 'YES' || $cwd_removable eq 'NO' or die;
7check_archive ($cwd_removable eq 'YES' ? {} : {"a" => {}});
8pass;
diff --git a/tests/filesys/extended/dir-rm-cwd.c b/tests/filesys/extended/dir-rm-cwd.c
new file mode 100644
index 0000000..78e13de
--- /dev/null
+++ b/tests/filesys/extended/dir-rm-cwd.c
@@ -0,0 +1,75 @@
1/* Tries to remove the current directory, which may succeed or
2 fail. The requirements in each case are different; refer to
3 the assignment for details. */
4
5#include <syscall.h>
6#include "tests/lib.h"
7#include "tests/main.h"
8
9static int
10wrap_open (const char *name)
11{
12 static int fds[8], fd_cnt;
13 int fd, i;
14
15 CHECK ((fd = open (name)) > 1, "open \"%s\"", name);
16 for (i = 0; i < fd_cnt; i++)
17 if (fds[i] == fd)
18 fail ("fd returned is not unique");
19 fds[fd_cnt++] = fd;
20 return fd;
21}
22
23void
24test_main (void)
25{
26 int root_fd, a_fd0;
27 char name[READDIR_MAX_LEN + 1];
28
29 root_fd = wrap_open ("/");
30 CHECK (mkdir ("a"), "mkdir \"a\"");
31
32 a_fd0 = wrap_open ("/a");
33 CHECK (!readdir (a_fd0, name), "verify \"/a\" is empty");
34 CHECK (inumber (root_fd) != inumber (a_fd0),
35 "\"/\" and \"/a\" must have different inumbers");
36
37 CHECK (chdir ("a"), "chdir \"a\"");
38
39 msg ("try to remove \"/a\"");
40 if (remove ("/a"))
41 {
42 msg ("remove successful");
43
44 CHECK (open ("/a") == -1, "open \"/a\" (must fail)");
45 CHECK (open (".") == -1, "open \".\" (must fail)");
46 CHECK (open ("..") == -1, "open \"..\" (must fail)");
47 CHECK (!create ("x", 512), "create \"x\" (must fail)");
48 }
49 else
50 {
51 int a_fd1, a_fd2, a_fd3;
52
53 msg ("remove failed");
54
55 CHECK (!remove ("../a"), "try to remove \"../a\" (must fail)");
56 CHECK (!remove (".././a"), "try to remove \".././a\" (must fail)");
57 CHECK (!remove ("/./a"), "try to remove \"/./a\" (must fail)");
58
59 a_fd1 = wrap_open ("/a");
60 a_fd2 = wrap_open (".");
61 CHECK (inumber (a_fd1) == inumber (a_fd2),
62 "\"/a\" and \".\" must have same inumber");
63 CHECK (inumber (root_fd) != inumber (a_fd1),
64 "\"/\" and \"/a\" must have different inumbers");
65
66 CHECK (chdir ("/a"), "chdir \"/a\"");
67 a_fd3 = wrap_open (".");
68 CHECK (inumber (a_fd3) == inumber (a_fd1),
69 "\".\" must have same inumber as before");
70
71 CHECK (chdir ("/"), "chdir \"/\"");
72 CHECK (!remove ("a"), "try to remove \"a\" (must fail: still open)");
73 }
74 CHECK (!readdir (a_fd0, name), "verify \"/a\" is empty");
75}
diff --git a/tests/filesys/extended/dir-rm-cwd.ck b/tests/filesys/extended/dir-rm-cwd.ck
new file mode 100644
index 0000000..6fa4739
--- /dev/null
+++ b/tests/filesys/extended/dir-rm-cwd.ck
@@ -0,0 +1,51 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5my ($cwd_removable) = check_expected (IGNORE_EXIT_CODES => 1,
6 {NO => <<'EOF', YES => <<'EOF'});
7(dir-rm-cwd) begin
8(dir-rm-cwd) open "/"
9(dir-rm-cwd) mkdir "a"
10(dir-rm-cwd) open "/a"
11(dir-rm-cwd) verify "/a" is empty
12(dir-rm-cwd) "/" and "/a" must have different inumbers
13(dir-rm-cwd) chdir "a"
14(dir-rm-cwd) try to remove "/a"
15(dir-rm-cwd) remove failed
16(dir-rm-cwd) try to remove "../a" (must fail)
17(dir-rm-cwd) try to remove ".././a" (must fail)
18(dir-rm-cwd) try to remove "/./a" (must fail)
19(dir-rm-cwd) open "/a"
20(dir-rm-cwd) open "."
21(dir-rm-cwd) "/a" and "." must have same inumber
22(dir-rm-cwd) "/" and "/a" must have different inumbers
23(dir-rm-cwd) chdir "/a"
24(dir-rm-cwd) open "."
25(dir-rm-cwd) "." must have same inumber as before
26(dir-rm-cwd) chdir "/"
27(dir-rm-cwd) try to remove "a" (must fail: still open)
28(dir-rm-cwd) verify "/a" is empty
29(dir-rm-cwd) end
30EOF
31(dir-rm-cwd) begin
32(dir-rm-cwd) open "/"
33(dir-rm-cwd) mkdir "a"
34(dir-rm-cwd) open "/a"
35(dir-rm-cwd) verify "/a" is empty
36(dir-rm-cwd) "/" and "/a" must have different inumbers
37(dir-rm-cwd) chdir "a"
38(dir-rm-cwd) try to remove "/a"
39(dir-rm-cwd) remove successful
40(dir-rm-cwd) open "/a" (must fail)
41(dir-rm-cwd) open "." (must fail)
42(dir-rm-cwd) open ".." (must fail)
43(dir-rm-cwd) create "x" (must fail)
44(dir-rm-cwd) verify "/a" is empty
45(dir-rm-cwd) end
46EOF
47open (CAN_RMDIR_CWD, ">tests/filesys/extended/can-rmdir-cwd")
48 or die "tests/filesys/extended/can-rmdir-cwd: create: $!\n";
49print CAN_RMDIR_CWD "$cwd_removable";
50close (CAN_RMDIR_CWD);
51pass;
diff --git a/tests/filesys/extended/dir-rm-parent-persistence.ck b/tests/filesys/extended/dir-rm-parent-persistence.ck
new file mode 100644
index 0000000..f30b04a
--- /dev/null
+++ b/tests/filesys/extended/dir-rm-parent-persistence.ck
@@ -0,0 +1,6 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_archive ({"a" => {"b" => {}}});
6pass;
diff --git a/tests/filesys/extended/dir-rm-parent.c b/tests/filesys/extended/dir-rm-parent.c
new file mode 100644
index 0000000..eb43f5b
--- /dev/null
+++ b/tests/filesys/extended/dir-rm-parent.c
@@ -0,0 +1,16 @@
1/* Tries to remove a parent of the current directory. This must
2 fail, because that directory is non-empty. */
3
4#include <syscall.h>
5#include "tests/lib.h"
6#include "tests/main.h"
7
8void
9test_main (void)
10{
11 CHECK (mkdir ("a"), "mkdir \"a\"");
12 CHECK (chdir ("a"), "chdir \"a\"");
13 CHECK (mkdir ("b"), "mkdir \"b\"");
14 CHECK (chdir ("b"), "chdir \"b\"");
15 CHECK (!remove ("/a"), "remove \"/a\" (must fail)");
16}
diff --git a/tests/filesys/extended/dir-rm-parent.ck b/tests/filesys/extended/dir-rm-parent.ck
new file mode 100644
index 0000000..9fea8f2
--- /dev/null
+++ b/tests/filesys/extended/dir-rm-parent.ck
@@ -0,0 +1,14 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(dir-rm-parent) begin
7(dir-rm-parent) mkdir "a"
8(dir-rm-parent) chdir "a"
9(dir-rm-parent) mkdir "b"
10(dir-rm-parent) chdir "b"
11(dir-rm-parent) remove "/a" (must fail)
12(dir-rm-parent) end
13EOF
14pass;
diff --git a/tests/filesys/extended/dir-rm-root-persistence.ck b/tests/filesys/extended/dir-rm-root-persistence.ck
new file mode 100644
index 0000000..6315107
--- /dev/null
+++ b/tests/filesys/extended/dir-rm-root-persistence.ck
@@ -0,0 +1,6 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_archive ({"a" => ["\0" x 243]});
6pass;
diff --git a/tests/filesys/extended/dir-rm-root.c b/tests/filesys/extended/dir-rm-root.c
new file mode 100644
index 0000000..c47f1eb
--- /dev/null
+++ b/tests/filesys/extended/dir-rm-root.c
@@ -0,0 +1,13 @@
1/* Try to remove the root directory.
2 This must fail. */
3
4#include <syscall.h>
5#include "tests/lib.h"
6#include "tests/main.h"
7
8void
9test_main (void)
10{
11 CHECK (!remove ("/"), "remove \"/\" (must fail)");
12 CHECK (create ("/a", 243), "create \"/a\"");
13}
diff --git a/tests/filesys/extended/dir-rm-root.ck b/tests/filesys/extended/dir-rm-root.ck
new file mode 100644
index 0000000..8a69ff3
--- /dev/null
+++ b/tests/filesys/extended/dir-rm-root.ck
@@ -0,0 +1,11 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(dir-rm-root) begin
7(dir-rm-root) remove "/" (must fail)
8(dir-rm-root) create "/a"
9(dir-rm-root) end
10EOF
11pass;
diff --git a/tests/filesys/extended/dir-rm-tree-persistence.ck b/tests/filesys/extended/dir-rm-tree-persistence.ck
new file mode 100644
index 0000000..562c451
--- /dev/null
+++ b/tests/filesys/extended/dir-rm-tree-persistence.ck
@@ -0,0 +1,6 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_archive ({});
6pass;
diff --git a/tests/filesys/extended/dir-rm-tree.c b/tests/filesys/extended/dir-rm-tree.c
new file mode 100644
index 0000000..bab41a6
--- /dev/null
+++ b/tests/filesys/extended/dir-rm-tree.c
@@ -0,0 +1,62 @@
1/* Creates directories /0/0/0 through /3/2/2 and files in the
2 leaf directories, then removes them. */
3
4#include <stdarg.h>
5#include <stdio.h>
6#include <syscall.h>
7#include "tests/filesys/extended/mk-tree.h"
8#include "tests/lib.h"
9#include "tests/main.h"
10
11static void remove_tree (int at, int bt, int ct, int dt);
12
13void
14test_main (void)
15{
16 make_tree (4, 3, 3, 4);
17 remove_tree (4, 3, 3, 4);
18}
19
20static void do_remove (const char *format, ...) PRINTF_FORMAT (1, 2);
21
22static void
23remove_tree (int at, int bt, int ct, int dt)
24{
25 char try[128];
26 int a, b, c, d;
27
28 msg ("removing /0/0/0/0 through /%d/%d/%d/%d...",
29 at - 1, bt - 1, ct - 1, dt - 1);
30 quiet = true;
31 for (a = 0; a < at; a++)
32 {
33 for (b = 0; b < bt; b++)
34 {
35 for (c = 0; c < ct; c++)
36 {
37 for (d = 0; d < dt; d++)
38 do_remove ("/%d/%d/%d/%d", a, b, c, d);
39 do_remove ("/%d/%d/%d", a, b, c);
40 }
41 do_remove ("/%d/%d", a, b);
42 }
43 do_remove ("/%d", a);
44 }
45 quiet = false;
46
47 snprintf (try, sizeof (try), "/%d/%d/%d/%d", at - 1, 0, ct - 1, 0);
48 CHECK (open (try) == -1, "open \"%s\" (must return -1)", try);
49}
50
51static void
52do_remove (const char *format, ...)
53{
54 char name[128];
55 va_list args;
56
57 va_start (args, format);
58 vsnprintf (name, sizeof name, format, args);
59 va_end (args);
60
61 CHECK (remove (name), "remove \"%s\"", name);
62}
diff --git a/tests/filesys/extended/dir-rm-tree.ck b/tests/filesys/extended/dir-rm-tree.ck
new file mode 100644
index 0000000..587b493
--- /dev/null
+++ b/tests/filesys/extended/dir-rm-tree.ck
@@ -0,0 +1,14 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(dir-rm-tree) begin
7(dir-rm-tree) creating /0/0/0/0 through /3/2/2/3...
8(dir-rm-tree) open "/0/2/0/3"
9(dir-rm-tree) close "/0/2/0/3"
10(dir-rm-tree) removing /0/0/0/0 through /3/2/2/3...
11(dir-rm-tree) open "/3/0/2/0" (must return -1)
12(dir-rm-tree) end
13EOF
14pass;
diff --git a/tests/filesys/extended/dir-rmdir-persistence.ck b/tests/filesys/extended/dir-rmdir-persistence.ck
new file mode 100644
index 0000000..562c451
--- /dev/null
+++ b/tests/filesys/extended/dir-rmdir-persistence.ck
@@ -0,0 +1,6 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_archive ({});
6pass;
diff --git a/tests/filesys/extended/dir-rmdir.c b/tests/filesys/extended/dir-rmdir.c
new file mode 100644
index 0000000..b3cbc6f
--- /dev/null
+++ b/tests/filesys/extended/dir-rmdir.c
@@ -0,0 +1,14 @@
1/* Creates and removes a directory, then makes sure that it's
2 really gone. */
3
4#include <syscall.h>
5#include "tests/lib.h"
6#include "tests/main.h"
7
8void
9test_main (void)
10{
11 CHECK (mkdir ("a"), "mkdir \"a\"");
12 CHECK (remove ("a"), "rmdir \"a\"");
13 CHECK (!chdir ("a"), "chdir \"a\" (must return false)");
14}
diff --git a/tests/filesys/extended/dir-rmdir.ck b/tests/filesys/extended/dir-rmdir.ck
new file mode 100644
index 0000000..e0d8922
--- /dev/null
+++ b/tests/filesys/extended/dir-rmdir.ck
@@ -0,0 +1,12 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(dir-rmdir) begin
7(dir-rmdir) mkdir "a"
8(dir-rmdir) rmdir "a"
9(dir-rmdir) chdir "a" (must return false)
10(dir-rmdir) end
11EOF
12pass;
diff --git a/tests/filesys/extended/dir-under-file-persistence.ck b/tests/filesys/extended/dir-under-file-persistence.ck
new file mode 100644
index 0000000..67ca528
--- /dev/null
+++ b/tests/filesys/extended/dir-under-file-persistence.ck
@@ -0,0 +1,6 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_archive ({"abc" => ['']});
6pass;
diff --git a/tests/filesys/extended/dir-under-file.c b/tests/filesys/extended/dir-under-file.c
new file mode 100644
index 0000000..973a8b1
--- /dev/null
+++ b/tests/filesys/extended/dir-under-file.c
@@ -0,0 +1,13 @@
1/* Tries to create a directory with the same name as an existing
2 file, which must return failure. */
3
4#include <syscall.h>
5#include "tests/lib.h"
6#include "tests/main.h"
7
8void
9test_main (void)
10{
11 CHECK (create ("abc", 0), "create \"abc\"");
12 CHECK (!mkdir ("abc"), "mkdir \"abc\" (must return false)");
13}
diff --git a/tests/filesys/extended/dir-under-file.ck b/tests/filesys/extended/dir-under-file.ck
new file mode 100644
index 0000000..cce23b4
--- /dev/null
+++ b/tests/filesys/extended/dir-under-file.ck
@@ -0,0 +1,11 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(dir-under-file) begin
7(dir-under-file) create "abc"
8(dir-under-file) mkdir "abc" (must return false)
9(dir-under-file) end
10EOF
11pass;
diff --git a/tests/filesys/extended/dir-vine-persistence.ck b/tests/filesys/extended/dir-vine-persistence.ck
new file mode 100644
index 0000000..698ef01
--- /dev/null
+++ b/tests/filesys/extended/dir-vine-persistence.ck
@@ -0,0 +1,37 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5# The archive should look like this:
6#
7# 40642 dir-vine
8# 42479 tar
9# 0 start
10# 11 start/file0
11# 0 start/dir0
12# 11 start/dir0/file1
13# 0 start/dir0/dir1
14# 11 start/dir0/dir1/file2
15# 0 start/dir0/dir1/dir2
16# 11 start/dir0/dir1/dir2/file3
17# 0 start/dir0/dir1/dir2/dir3
18# 11 start/dir0/dir1/dir2/dir3/file4
19# 0 start/dir0/dir1/dir2/dir3/dir4
20# 11 start/dir0/dir1/dir2/dir3/dir4/file5
21# 0 start/dir0/dir1/dir2/dir3/dir4/dir5
22# 11 start/dir0/dir1/dir2/dir3/dir4/dir5/file6
23# 0 start/dir0/dir1/dir2/dir3/dir4/dir5/dir6
24# 11 start/dir0/dir1/dir2/dir3/dir4/dir5/dir6/file7
25# 0 start/dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7
26# 11 start/dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/file8
27# 0 start/dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8
28# 11 start/dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/file9
29# 0 start/dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9
30my ($dir) = {};
31my ($root) = {"start" => $dir};
32for (my ($i) = 0; $i < 10; $i++) {
33 $dir->{"file$i"} = ["contents $i\n"];
34 $dir = $dir->{"dir$i"} = {};
35}
36check_archive ($root);
37pass;
diff --git a/tests/filesys/extended/dir-vine.c b/tests/filesys/extended/dir-vine.c
new file mode 100644
index 0000000..8a31c38
--- /dev/null
+++ b/tests/filesys/extended/dir-vine.c
@@ -0,0 +1,85 @@
1/* Create a very deep "vine" of directories: /dir0/dir1/dir2/...
2 and an ordinary file in each of them, until we fill up the
3 disk.
4
5 Then delete most of them, for two reasons. First, "tar"
6 limits file names to 100 characters (which could be extended
7 to 256 without much trouble). Second, a full disk has no room
8 for the tar archive. */
9
10#include <string.h>
11#include <stdio.h>
12#include <syscall.h>
13#include "tests/lib.h"
14#include "tests/main.h"
15
16void
17test_main (void)
18{
19 int i;
20
21 msg ("creating many levels of files and directories...");
22 quiet = true;
23 CHECK (mkdir ("start"), "mkdir \"start\"");
24 CHECK (chdir ("start"), "chdir \"start\"");
25 for (i = 0; ; i++)
26 {
27 char name[3][READDIR_MAX_LEN + 1];
28 char file_name[16], dir_name[16];
29 char contents[128];
30 int fd;
31
32 /* Create file. */
33 snprintf (file_name, sizeof file_name, "file%d", i);
34 if (!create (file_name, 0))
35 break;
36 CHECK ((fd = open (file_name)) > 1, "open \"%s\"", file_name);
37 snprintf (contents, sizeof contents, "contents %d\n", i);
38 if (write (fd, contents, strlen (contents)) != (int) strlen (contents))
39 {
40 CHECK (remove (file_name), "remove \"%s\"", file_name);
41 close (fd);
42 break;
43 }
44 close (fd);
45
46 /* Create directory. */
47 snprintf (dir_name, sizeof dir_name, "dir%d", i);
48 if (!mkdir (dir_name))
49 {
50 CHECK (remove (file_name), "remove \"%s\"", file_name);
51 break;
52 }
53
54 /* Check for file and directory. */
55 CHECK ((fd = open (".")) > 1, "open \".\"");
56 CHECK (readdir (fd, name[0]), "readdir \".\"");
57 CHECK (readdir (fd, name[1]), "readdir \".\"");
58 CHECK (!readdir (fd, name[2]), "readdir \".\" (should fail)");
59 CHECK ((!strcmp (name[0], dir_name) && !strcmp (name[1], file_name))
60 || (!strcmp (name[1], dir_name) && !strcmp (name[0], file_name)),
61 "names should be \"%s\" and \"%s\", "
62 "actually \"%s\" and \"%s\"",
63 file_name, dir_name, name[0], name[1]);
64 close (fd);
65
66 /* Descend into directory. */
67 CHECK (chdir (dir_name), "chdir \"%s\"", dir_name);
68 }
69 CHECK (i > 200, "created files and directories only to level %d", i);
70 quiet = false;
71
72 msg ("removing all but top 10 levels of files and directories...");
73 quiet = true;
74 while (i-- > 10)
75 {
76 char file_name[16], dir_name[16];
77
78 snprintf (file_name, sizeof file_name, "file%d", i);
79 snprintf (dir_name, sizeof dir_name, "dir%d", i);
80 CHECK (chdir (".."), "chdir \"..\"");
81 CHECK (remove (dir_name), "remove \"%s\"", dir_name);
82 CHECK (remove (file_name), "remove \"%s\"", file_name);
83 }
84 quiet = false;
85}
diff --git a/tests/filesys/extended/dir-vine.ck b/tests/filesys/extended/dir-vine.ck
new file mode 100644
index 0000000..db452b0
--- /dev/null
+++ b/tests/filesys/extended/dir-vine.ck
@@ -0,0 +1,11 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(dir-vine) begin
7(dir-vine) creating many levels of files and directories...
8(dir-vine) removing all but top 10 levels of files and directories...
9(dir-vine) end
10EOF
11pass;
diff --git a/tests/filesys/extended/grow-create-persistence.ck b/tests/filesys/extended/grow-create-persistence.ck
new file mode 100644
index 0000000..bbcb24f
--- /dev/null
+++ b/tests/filesys/extended/grow-create-persistence.ck
@@ -0,0 +1,6 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_archive ({"blargle" => ['']});
6pass;
diff --git a/tests/filesys/extended/grow-create.c b/tests/filesys/extended/grow-create.c
new file mode 100644
index 0000000..9ccc4ea
--- /dev/null
+++ b/tests/filesys/extended/grow-create.c
@@ -0,0 +1,4 @@
1/* Create a file of size 0. */
2
3#define TEST_SIZE 0
4#include "tests/filesys/create.inc"
diff --git a/tests/filesys/extended/grow-create.ck b/tests/filesys/extended/grow-create.ck
new file mode 100644
index 0000000..b2e69d1
--- /dev/null
+++ b/tests/filesys/extended/grow-create.ck
@@ -0,0 +1,13 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(grow-create) begin
7(grow-create) create "blargle"
8(grow-create) open "blargle" for verification
9(grow-create) verified contents of "blargle"
10(grow-create) close "blargle"
11(grow-create) end
12EOF
13pass;
diff --git a/tests/filesys/extended/grow-dir-lg-persistence.ck b/tests/filesys/extended/grow-dir-lg-persistence.ck
new file mode 100644
index 0000000..989a322
--- /dev/null
+++ b/tests/filesys/extended/grow-dir-lg-persistence.ck
@@ -0,0 +1,9 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5use tests::random;
6my ($fs);
7$fs->{'x'}{"file$_"} = [random_bytes (512)] foreach 0...49;
8check_archive ($fs);
9pass;
diff --git a/tests/filesys/extended/grow-dir-lg.c b/tests/filesys/extended/grow-dir-lg.c
new file mode 100644
index 0000000..20a194b
--- /dev/null
+++ b/tests/filesys/extended/grow-dir-lg.c
@@ -0,0 +1,6 @@
1/* Creates a directory,
2 then creates 50 files in that directory. */
3
4#define FILE_CNT 50
5#define DIRECTORY "/x"
6#include "tests/filesys/extended/grow-dir.inc"
diff --git a/tests/filesys/extended/grow-dir-lg.ck b/tests/filesys/extended/grow-dir-lg.ck
new file mode 100644
index 0000000..ec58bd3
--- /dev/null
+++ b/tests/filesys/extended/grow-dir-lg.ck
@@ -0,0 +1,61 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5use tests::random;
6check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
7(grow-dir-lg) begin
8(grow-dir-lg) mkdir /x
9(grow-dir-lg) creating and checking "/x/file0"
10(grow-dir-lg) creating and checking "/x/file1"
11(grow-dir-lg) creating and checking "/x/file2"
12(grow-dir-lg) creating and checking "/x/file3"
13(grow-dir-lg) creating and checking "/x/file4"
14(grow-dir-lg) creating and checking "/x/file5"
15(grow-dir-lg) creating and checking "/x/file6"
16(grow-dir-lg) creating and checking "/x/file7"
17(grow-dir-lg) creating and checking "/x/file8"
18(grow-dir-lg) creating and checking "/x/file9"
19(grow-dir-lg) creating and checking "/x/file10"
20(grow-dir-lg) creating and checking "/x/file11"
21(grow-dir-lg) creating and checking "/x/file12"
22(grow-dir-lg) creating and checking "/x/file13"
23(grow-dir-lg) creating and checking "/x/file14"
24(grow-dir-lg) creating and checking "/x/file15"
25(grow-dir-lg) creating and checking "/x/file16"
26(grow-dir-lg) creating and checking "/x/file17"
27(grow-dir-lg) creating and checking "/x/file18"
28(grow-dir-lg) creating and checking "/x/file19"
29(grow-dir-lg) creating and checking "/x/file20"
30(grow-dir-lg) creating and checking "/x/file21"
31(grow-dir-lg) creating and checking "/x/file22"
32(grow-dir-lg) creating and checking "/x/file23"
33(grow-dir-lg) creating and checking "/x/file24"
34(grow-dir-lg) creating and checking "/x/file25"
35(grow-dir-lg) creating and checking "/x/file26"
36(grow-dir-lg) creating and checking "/x/file27"
37(grow-dir-lg) creating and checking "/x/file28"
38(grow-dir-lg) creating and checking "/x/file29"
39(grow-dir-lg) creating and checking "/x/file30"
40(grow-dir-lg) creating and checking "/x/file31"
41(grow-dir-lg) creating and checking "/x/file32"
42(grow-dir-lg) creating and checking "/x/file33"
43(grow-dir-lg) creating and checking "/x/file34"
44(grow-dir-lg) creating and checking "/x/file35"
45(grow-dir-lg) creating and checking "/x/file36"
46(grow-dir-lg) creating and checking "/x/file37"
47(grow-dir-lg) creating and checking "/x/file38"
48(grow-dir-lg) creating and checking "/x/file39"
49(grow-dir-lg) creating and checking "/x/file40"
50(grow-dir-lg) creating and checking "/x/file41"
51(grow-dir-lg) creating and checking "/x/file42"
52(grow-dir-lg) creating and checking "/x/file43"
53(grow-dir-lg) creating and checking "/x/file44"
54(grow-dir-lg) creating and checking "/x/file45"
55(grow-dir-lg) creating and checking "/x/file46"
56(grow-dir-lg) creating and checking "/x/file47"
57(grow-dir-lg) creating and checking "/x/file48"
58(grow-dir-lg) creating and checking "/x/file49"
59(grow-dir-lg) end
60EOF
61pass;
diff --git a/tests/filesys/extended/grow-dir.inc b/tests/filesys/extended/grow-dir.inc
new file mode 100644
index 0000000..bee0ba0
--- /dev/null
+++ b/tests/filesys/extended/grow-dir.inc
@@ -0,0 +1,41 @@
1/* -*- c -*- */
2
3#include <syscall.h>
4#include <stdio.h>
5#include "tests/filesys/seq-test.h"
6#include "tests/lib.h"
7#include "tests/main.h"
8
9static char buf[512];
10
11static size_t
12return_block_size (void)
13{
14 return sizeof buf;
15}
16
17void
18test_main (void)
19{
20 size_t i;
21
22#ifdef DIRECTORY
23 CHECK (mkdir (DIRECTORY), "mkdir %s", DIRECTORY);
24#define DIR_PREFIX DIRECTORY "/"
25#else
26#define DIR_PREFIX ""
27#endif
28 for (i = 0; i < FILE_CNT; i++)
29 {
30 char file_name[128];
31 snprintf (file_name, sizeof file_name, "%sfile%zu", DIR_PREFIX, i);
32
33 msg ("creating and checking \"%s\"", file_name);
34
35 quiet = true;
36 seq_test (file_name,
37 buf, sizeof buf, sizeof buf,
38 return_block_size, NULL);
39 quiet = false;
40 }
41}
diff --git a/tests/filesys/extended/grow-file-size-persistence.ck b/tests/filesys/extended/grow-file-size-persistence.ck
new file mode 100644
index 0000000..150f383
--- /dev/null
+++ b/tests/filesys/extended/grow-file-size-persistence.ck
@@ -0,0 +1,7 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5use tests::random;
6check_archive ({"testfile" => [random_bytes (2134)]});
7pass;
diff --git a/tests/filesys/extended/grow-file-size.c b/tests/filesys/extended/grow-file-size.c
new file mode 100644
index 0000000..3ce8588
--- /dev/null
+++ b/tests/filesys/extended/grow-file-size.c
@@ -0,0 +1,33 @@
1/* Grows a file from 0 bytes to 2,134 bytes, 37 bytes at a time,
2 and checks that the file's size is reported correctly at each
3 step. */
4
5#include <syscall.h>
6#include "tests/filesys/seq-test.h"
7#include "tests/lib.h"
8#include "tests/main.h"
9
10static char buf[2134];
11
12static size_t
13return_block_size (void)
14{
15 return 37;
16}
17
18static void
19check_file_size (int fd, long ofs)
20{
21 long size = filesize (fd);
22 if (size != ofs)
23 fail ("filesize not updated properly: should be %ld, actually %ld",
24 ofs, size);
25}
26
27void
28test_main (void)
29{
30 seq_test ("testfile",
31 buf, sizeof buf, 0,
32 return_block_size, check_file_size);
33}
diff --git a/tests/filesys/extended/grow-file-size.ck b/tests/filesys/extended/grow-file-size.ck
new file mode 100644
index 0000000..d81feff
--- /dev/null
+++ b/tests/filesys/extended/grow-file-size.ck
@@ -0,0 +1,17 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5use tests::random;
6check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
7(grow-file-size) begin
8(grow-file-size) create "testfile"
9(grow-file-size) open "testfile"
10(grow-file-size) writing "testfile"
11(grow-file-size) close "testfile"
12(grow-file-size) open "testfile" for verification
13(grow-file-size) verified contents of "testfile"
14(grow-file-size) close "testfile"
15(grow-file-size) end
16EOF
17pass;
diff --git a/tests/filesys/extended/grow-root-lg-persistence.ck b/tests/filesys/extended/grow-root-lg-persistence.ck
new file mode 100644
index 0000000..1692f46
--- /dev/null
+++ b/tests/filesys/extended/grow-root-lg-persistence.ck
@@ -0,0 +1,9 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5use tests::random;
6my ($fs);
7$fs->{"file$_"} = [random_bytes (512)] foreach 0...49;
8check_archive ($fs);
9pass;
diff --git a/tests/filesys/extended/grow-root-lg.c b/tests/filesys/extended/grow-root-lg.c
new file mode 100644
index 0000000..d8d6c09
--- /dev/null
+++ b/tests/filesys/extended/grow-root-lg.c
@@ -0,0 +1,4 @@
1/* Creates 50 files in the root directory. */
2
3#define FILE_CNT 50
4#include "tests/filesys/extended/grow-dir.inc"
diff --git a/tests/filesys/extended/grow-root-lg.ck b/tests/filesys/extended/grow-root-lg.ck
new file mode 100644
index 0000000..b174bc9
--- /dev/null
+++ b/tests/filesys/extended/grow-root-lg.ck
@@ -0,0 +1,60 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5use tests::random;
6check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
7(grow-root-lg) begin
8(grow-root-lg) creating and checking "file0"
9(grow-root-lg) creating and checking "file1"
10(grow-root-lg) creating and checking "file2"
11(grow-root-lg) creating and checking "file3"
12(grow-root-lg) creating and checking "file4"
13(grow-root-lg) creating and checking "file5"
14(grow-root-lg) creating and checking "file6"
15(grow-root-lg) creating and checking "file7"
16(grow-root-lg) creating and checking "file8"
17(grow-root-lg) creating and checking "file9"
18(grow-root-lg) creating and checking "file10"
19(grow-root-lg) creating and checking "file11"
20(grow-root-lg) creating and checking "file12"
21(grow-root-lg) creating and checking "file13"
22(grow-root-lg) creating and checking "file14"
23(grow-root-lg) creating and checking "file15"
24(grow-root-lg) creating and checking "file16"
25(grow-root-lg) creating and checking "file17"
26(grow-root-lg) creating and checking "file18"
27(grow-root-lg) creating and checking "file19"
28(grow-root-lg) creating and checking "file20"
29(grow-root-lg) creating and checking "file21"
30(grow-root-lg) creating and checking "file22"
31(grow-root-lg) creating and checking "file23"
32(grow-root-lg) creating and checking "file24"
33(grow-root-lg) creating and checking "file25"
34(grow-root-lg) creating and checking "file26"
35(grow-root-lg) creating and checking "file27"
36(grow-root-lg) creating and checking "file28"
37(grow-root-lg) creating and checking "file29"
38(grow-root-lg) creating and checking "file30"
39(grow-root-lg) creating and checking "file31"
40(grow-root-lg) creating and checking "file32"
41(grow-root-lg) creating and checking "file33"
42(grow-root-lg) creating and checking "file34"
43(grow-root-lg) creating and checking "file35"
44(grow-root-lg) creating and checking "file36"
45(grow-root-lg) creating and checking "file37"
46(grow-root-lg) creating and checking "file38"
47(grow-root-lg) creating and checking "file39"
48(grow-root-lg) creating and checking "file40"
49(grow-root-lg) creating and checking "file41"
50(grow-root-lg) creating and checking "file42"
51(grow-root-lg) creating and checking "file43"
52(grow-root-lg) creating and checking "file44"
53(grow-root-lg) creating and checking "file45"
54(grow-root-lg) creating and checking "file46"
55(grow-root-lg) creating and checking "file47"
56(grow-root-lg) creating and checking "file48"
57(grow-root-lg) creating and checking "file49"
58(grow-root-lg) end
59EOF
60pass;
diff --git a/tests/filesys/extended/grow-root-sm-persistence.ck b/tests/filesys/extended/grow-root-sm-persistence.ck
new file mode 100644
index 0000000..2b0b8ab
--- /dev/null
+++ b/tests/filesys/extended/grow-root-sm-persistence.ck
@@ -0,0 +1,9 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5use tests::random;
6my ($fs);
7$fs->{"file$_"} = [random_bytes (512)] foreach 0...19;
8check_archive ($fs);
9pass;
diff --git a/tests/filesys/extended/grow-root-sm.c b/tests/filesys/extended/grow-root-sm.c
new file mode 100644
index 0000000..ee375d5
--- /dev/null
+++ b/tests/filesys/extended/grow-root-sm.c
@@ -0,0 +1,4 @@
1/* Creates 20 files in the root directory. */
2
3#define FILE_CNT 20
4#include "tests/filesys/extended/grow-dir.inc"
diff --git a/tests/filesys/extended/grow-root-sm.ck b/tests/filesys/extended/grow-root-sm.ck
new file mode 100644
index 0000000..1aac7e9
--- /dev/null
+++ b/tests/filesys/extended/grow-root-sm.ck
@@ -0,0 +1,30 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5use tests::random;
6check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
7(grow-root-sm) begin
8(grow-root-sm) creating and checking "file0"
9(grow-root-sm) creating and checking "file1"
10(grow-root-sm) creating and checking "file2"
11(grow-root-sm) creating and checking "file3"
12(grow-root-sm) creating and checking "file4"
13(grow-root-sm) creating and checking "file5"
14(grow-root-sm) creating and checking "file6"
15(grow-root-sm) creating and checking "file7"
16(grow-root-sm) creating and checking "file8"
17(grow-root-sm) creating and checking "file9"
18(grow-root-sm) creating and checking "file10"
19(grow-root-sm) creating and checking "file11"
20(grow-root-sm) creating and checking "file12"
21(grow-root-sm) creating and checking "file13"
22(grow-root-sm) creating and checking "file14"
23(grow-root-sm) creating and checking "file15"
24(grow-root-sm) creating and checking "file16"
25(grow-root-sm) creating and checking "file17"
26(grow-root-sm) creating and checking "file18"
27(grow-root-sm) creating and checking "file19"
28(grow-root-sm) end
29EOF
30pass;
diff --git a/tests/filesys/extended/grow-seq-lg-persistence.ck b/tests/filesys/extended/grow-seq-lg-persistence.ck
new file mode 100644
index 0000000..41aaae0
--- /dev/null
+++ b/tests/filesys/extended/grow-seq-lg-persistence.ck
@@ -0,0 +1,7 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5use tests::random;
6check_archive ({"testme" => [random_bytes (72943)]});
7pass;
diff --git a/tests/filesys/extended/grow-seq-lg.c b/tests/filesys/extended/grow-seq-lg.c
new file mode 100644
index 0000000..3108d17
--- /dev/null
+++ b/tests/filesys/extended/grow-seq-lg.c
@@ -0,0 +1,5 @@
1/* Grows a file from 0 bytes to 72,943 bytes, 1,234 bytes at a
2 time. */
3
4#define TEST_SIZE 72943
5#include "tests/filesys/extended/grow-seq.inc"
diff --git a/tests/filesys/extended/grow-seq-lg.ck b/tests/filesys/extended/grow-seq-lg.ck
new file mode 100644
index 0000000..90fcd8c
--- /dev/null
+++ b/tests/filesys/extended/grow-seq-lg.ck
@@ -0,0 +1,17 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5use tests::random;
6check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
7(grow-seq-lg) begin
8(grow-seq-lg) create "testme"
9(grow-seq-lg) open "testme"
10(grow-seq-lg) writing "testme"
11(grow-seq-lg) close "testme"
12(grow-seq-lg) open "testme" for verification
13(grow-seq-lg) verified contents of "testme"
14(grow-seq-lg) close "testme"
15(grow-seq-lg) end
16EOF
17pass;
diff --git a/tests/filesys/extended/grow-seq-sm-persistence.ck b/tests/filesys/extended/grow-seq-sm-persistence.ck
new file mode 100644
index 0000000..6cb0bd8
--- /dev/null
+++ b/tests/filesys/extended/grow-seq-sm-persistence.ck
@@ -0,0 +1,7 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5use tests::random;
6check_archive ({"testme" => [random_bytes (5678)]});
7pass;
diff --git a/tests/filesys/extended/grow-seq-sm.c b/tests/filesys/extended/grow-seq-sm.c
new file mode 100644
index 0000000..3656e2e
--- /dev/null
+++ b/tests/filesys/extended/grow-seq-sm.c
@@ -0,0 +1,5 @@
1/* Grows a file from 0 bytes to 5,678 bytes, 1,234 bytes at a
2 time. */
3
4#define TEST_SIZE 5678
5#include "tests/filesys/extended/grow-seq.inc"
diff --git a/tests/filesys/extended/grow-seq-sm.ck b/tests/filesys/extended/grow-seq-sm.ck
new file mode 100644
index 0000000..5cf4518
--- /dev/null
+++ b/tests/filesys/extended/grow-seq-sm.ck
@@ -0,0 +1,17 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5use tests::random;
6check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
7(grow-seq-sm) begin
8(grow-seq-sm) create "testme"
9(grow-seq-sm) open "testme"
10(grow-seq-sm) writing "testme"
11(grow-seq-sm) close "testme"
12(grow-seq-sm) open "testme" for verification
13(grow-seq-sm) verified contents of "testme"
14(grow-seq-sm) close "testme"
15(grow-seq-sm) end
16EOF
17pass;
diff --git a/tests/filesys/extended/grow-seq.inc b/tests/filesys/extended/grow-seq.inc
new file mode 100644
index 0000000..1b7710c
--- /dev/null
+++ b/tests/filesys/extended/grow-seq.inc
@@ -0,0 +1,20 @@
1/* -*- c -*- */
2
3#include "tests/filesys/seq-test.h"
4#include "tests/main.h"
5
6static char buf[TEST_SIZE];
7
8static size_t
9return_block_size (void)
10{
11 return 1234;
12}
13
14void
15test_main (void)
16{
17 seq_test ("testme",
18 buf, sizeof buf, 0,
19 return_block_size, NULL);
20}
diff --git a/tests/filesys/extended/grow-sparse-persistence.ck b/tests/filesys/extended/grow-sparse-persistence.ck
new file mode 100644
index 0000000..3f06a5b
--- /dev/null
+++ b/tests/filesys/extended/grow-sparse-persistence.ck
@@ -0,0 +1,6 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_archive ({"testfile" => ["\0" x 76543]});
6pass;
diff --git a/tests/filesys/extended/grow-sparse.c b/tests/filesys/extended/grow-sparse.c
new file mode 100644
index 0000000..6eab210
--- /dev/null
+++ b/tests/filesys/extended/grow-sparse.c
@@ -0,0 +1,25 @@
1/* Tests that seeking past the end of a file and writing will
2 properly zero out the region in between. */
3
4#include <syscall.h>
5#include "tests/lib.h"
6#include "tests/main.h"
7
8static char buf[76543];
9
10void
11test_main (void)
12{
13 const char *file_name = "testfile";
14 char zero = 0;
15 int fd;
16
17 CHECK (create (file_name, 0), "create \"%s\"", file_name);
18 CHECK ((fd = open (file_name)) > 1, "open \"%s\"", file_name);
19 msg ("seek \"%s\"", file_name);
20 seek (fd, sizeof buf - 1);
21 CHECK (write (fd, &zero, 1) > 0, "write \"%s\"", file_name);
22 msg ("close \"%s\"", file_name);
23 close (fd);
24 check_file (file_name, buf, sizeof buf);
25}
diff --git a/tests/filesys/extended/grow-sparse.ck b/tests/filesys/extended/grow-sparse.ck
new file mode 100644
index 0000000..379ba2c
--- /dev/null
+++ b/tests/filesys/extended/grow-sparse.ck
@@ -0,0 +1,17 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
6(grow-sparse) begin
7(grow-sparse) create "testfile"
8(grow-sparse) open "testfile"
9(grow-sparse) seek "testfile"
10(grow-sparse) write "testfile"
11(grow-sparse) close "testfile"
12(grow-sparse) open "testfile" for verification
13(grow-sparse) verified contents of "testfile"
14(grow-sparse) close "testfile"
15(grow-sparse) end
16EOF
17pass;
diff --git a/tests/filesys/extended/grow-tell-persistence.ck b/tests/filesys/extended/grow-tell-persistence.ck
new file mode 100644
index 0000000..d93a422
--- /dev/null
+++ b/tests/filesys/extended/grow-tell-persistence.ck
@@ -0,0 +1,7 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5use tests::random;
6check_archive ({"foobar" => [random_bytes (2134)]});
7pass;
diff --git a/tests/filesys/extended/grow-tell.c b/tests/filesys/extended/grow-tell.c
new file mode 100644
index 0000000..5f5da5b
--- /dev/null
+++ b/tests/filesys/extended/grow-tell.c
@@ -0,0 +1,32 @@
1/* Checks that growing a file updates the file position
2 correctly. */
3
4#include <syscall.h>
5#include "tests/filesys/seq-test.h"
6#include "tests/lib.h"
7#include "tests/main.h"
8
9static char buf[2134];
10
11static size_t
12return_block_size (void)
13{
14 return 37;
15}
16
17static void
18check_tell (int fd, long ofs)
19{
20 long pos = tell (fd);
21 if (pos != ofs)
22 fail ("file position not updated properly: should be %ld, actually %ld",
23 ofs, pos);
24}
25
26void
27test_main (void)
28{
29 seq_test ("foobar",
30 buf, sizeof buf, 0,
31 return_block_size, check_tell);
32}
diff --git a/tests/filesys/extended/grow-tell.ck b/tests/filesys/extended/grow-tell.ck
new file mode 100644
index 0000000..fe94707
--- /dev/null
+++ b/tests/filesys/extended/grow-tell.ck
@@ -0,0 +1,17 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5use tests::random;
6check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
7(grow-tell) begin
8(grow-tell) create "foobar"
9(grow-tell) open "foobar"
10(grow-tell) writing "foobar"
11(grow-tell) close "foobar"
12(grow-tell) open "foobar" for verification
13(grow-tell) verified contents of "foobar"
14(grow-tell) close "foobar"
15(grow-tell) end
16EOF
17pass;
diff --git a/tests/filesys/extended/grow-two-files-persistence.ck b/tests/filesys/extended/grow-two-files-persistence.ck
new file mode 100644
index 0000000..1c4ced1
--- /dev/null
+++ b/tests/filesys/extended/grow-two-files-persistence.ck
@@ -0,0 +1,9 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5use tests::random;
6my ($a) = random_bytes (8143);
7my ($b) = random_bytes (8143);
8check_archive ({"a" => [$a], "b" => [$b]});
9pass;
diff --git a/tests/filesys/extended/grow-two-files.c b/tests/filesys/extended/grow-two-files.c
new file mode 100644
index 0000000..6a8fb1c
--- /dev/null
+++ b/tests/filesys/extended/grow-two-files.c
@@ -0,0 +1,62 @@
1/* Grows two files in parallel and checks that their contents are
2 correct. */
3
4#include <random.h>
5#include <syscall.h>
6#include "tests/lib.h"
7#include "tests/main.h"
8
9#define FILE_SIZE 8143
10static char buf_a[FILE_SIZE];
11static char buf_b[FILE_SIZE];
12
13static void
14write_some_bytes (const char *file_name, int fd, const char *buf, size_t *ofs)
15{
16 if (*ofs < FILE_SIZE)
17 {
18 size_t block_size = random_ulong () % (FILE_SIZE / 8) + 1;
19 size_t ret_val;
20 if (block_size > FILE_SIZE - *ofs)
21 block_size = FILE_SIZE - *ofs;
22
23 ret_val = write (fd, buf + *ofs, block_size);
24 if (ret_val != block_size)
25 fail ("write %zu bytes at offset %zu in \"%s\" returned %zu",
26 block_size, *ofs, file_name, ret_val);
27 *ofs += block_size;
28 }
29}
30
31void
32test_main (void)
33{
34 int fd_a, fd_b;
35 size_t ofs_a = 0, ofs_b = 0;
36
37 random_init (0);
38 random_bytes (buf_a, sizeof buf_a);
39 random_bytes (buf_b, sizeof buf_b);
40
41 CHECK (create ("a", 0), "create \"a\"");
42 CHECK (create ("b", 0), "create \"b\"");
43
44 CHECK ((fd_a = open ("a")) > 1, "open \"a\"");
45 CHECK ((fd_b = open ("b")) > 1, "open \"b\"");
46
47 msg ("write \"a\" and \"b\" alternately");
48 while (ofs_a < FILE_SIZE || ofs_b < FILE_SIZE)
49 {
50 write_some_bytes ("a", fd_a, buf_a, &ofs_a);
51 write_some_bytes ("b", fd_b, buf_b, &ofs_b);
52 }
53
54 msg ("close \"a\"");
55 close (fd_a);
56
57 msg ("close \"b\"");
58 close (fd_b);
59
60 check_file ("a", buf_a, FILE_SIZE);
61 check_file ("b", buf_b, FILE_SIZE);
62}
diff --git a/tests/filesys/extended/grow-two-files.ck b/tests/filesys/extended/grow-two-files.ck
new file mode 100644
index 0000000..b5e754a
--- /dev/null
+++ b/tests/filesys/extended/grow-two-files.ck
@@ -0,0 +1,23 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5use tests::random;
6check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
7(grow-two-files) begin
8(grow-two-files) create "a"
9(grow-two-files) create "b"
10(grow-two-files) open "a"
11(grow-two-files) open "b"
12(grow-two-files) write "a" and "b" alternately
13(grow-two-files) close "a"
14(grow-two-files) close "b"
15(grow-two-files) open "a" for verification
16(grow-two-files) verified contents of "a"
17(grow-two-files) close "a"
18(grow-two-files) open "b" for verification
19(grow-two-files) verified contents of "b"
20(grow-two-files) close "b"
21(grow-two-files) end
22EOF
23pass;
diff --git a/tests/filesys/extended/mk-tree.c b/tests/filesys/extended/mk-tree.c
new file mode 100644
index 0000000..a36bb88
--- /dev/null
+++ b/tests/filesys/extended/mk-tree.c
@@ -0,0 +1,67 @@
1/* Library function for creating a tree of directories. */
2
3#include <stdio.h>
4#include <syscall.h>
5#include "tests/filesys/extended/mk-tree.h"
6#include "tests/lib.h"
7
8static void do_mkdir (const char *format, ...) PRINTF_FORMAT (1, 2);
9static void do_touch (const char *format, ...) PRINTF_FORMAT (1, 2);
10
11void
12make_tree (int at, int bt, int ct, int dt)
13{
14 char try[128];
15 int a, b, c, d;
16 int fd;
17
18 msg ("creating /0/0/0/0 through /%d/%d/%d/%d...",
19 at - 1, bt - 1, ct - 1, dt - 1);
20 quiet = true;
21 for (a = 0; a < at; a++)
22 {
23 do_mkdir ("/%d", a);
24 for (b = 0; b < bt; b++)
25 {
26 do_mkdir ("/%d/%d", a, b);
27 for (c = 0; c < ct; c++)
28 {
29 do_mkdir ("/%d/%d/%d", a, b, c);
30 for (d = 0; d < dt; d++)
31 do_touch ("/%d/%d/%d/%d", a, b, c, d);
32 }
33 }
34 }
35 quiet = false;
36
37 snprintf (try, sizeof try, "/%d/%d/%d/%d", 0, bt - 1, 0, dt - 1);
38 CHECK ((fd = open (try)) > 1, "open \"%s\"", try);
39 msg ("close \"%s\"", try);
40 close (fd);
41}
42
43static void
44do_mkdir (const char *format, ...)
45{
46 char dir[128];
47 va_list args;
48
49 va_start (args, format);
50 vsnprintf (dir, sizeof dir, format, args);
51 va_end (args);
52
53 CHECK (mkdir (dir), "mkdir \"%s\"", dir);
54}
55
56static void
57do_touch (const char *format, ...)
58{
59 char file[128];
60 va_list args;
61
62 va_start (args, format);
63 vsnprintf (file, sizeof file, format, args);
64 va_end (args);
65
66 CHECK (create (file, 0), "create \"%s\"", file);
67}
diff --git a/tests/filesys/extended/mk-tree.h b/tests/filesys/extended/mk-tree.h
new file mode 100644
index 0000000..df0d5a6
--- /dev/null
+++ b/tests/filesys/extended/mk-tree.h
@@ -0,0 +1,6 @@
1#ifndef TESTS_FILESYS_EXTENDED_MK_TREE_H
2#define TESTS_FILESYS_EXTENDED_MK_TREE_H
3
4void make_tree (int at, int bt, int ct, int dt);
5
6#endif /* tests/filesys/extended/mk-tree.h */
diff --git a/tests/filesys/extended/syn-rw-persistence.ck b/tests/filesys/extended/syn-rw-persistence.ck
new file mode 100644
index 0000000..62d57ee
--- /dev/null
+++ b/tests/filesys/extended/syn-rw-persistence.ck
@@ -0,0 +1,8 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5use tests::random;
6check_archive ({"child-syn-rw" => "tests/filesys/extended/child-syn-rw",
7 "logfile" => [random_bytes (8 * 512)]});
8pass;
diff --git a/tests/filesys/extended/syn-rw.c b/tests/filesys/extended/syn-rw.c
new file mode 100644
index 0000000..657dfb5
--- /dev/null
+++ b/tests/filesys/extended/syn-rw.c
@@ -0,0 +1,35 @@
1/* Grows a file in chunks while subprocesses read the growing
2 file. */
3
4#include <random.h>
5#include <syscall.h>
6#include "tests/filesys/extended/syn-rw.h"
7#include "tests/lib.h"
8#include "tests/main.h"
9
10char buf[BUF_SIZE];
11
12#define CHILD_CNT 4
13
14void
15test_main (void)
16{
17 pid_t children[CHILD_CNT];
18 size_t ofs;
19 int fd;
20
21 CHECK (create (file_name, 0), "create \"%s\"", file_name);
22 CHECK ((fd = open (file_name)) > 1, "open \"%s\"", file_name);
23
24 exec_children ("child-syn-rw", children, CHILD_CNT);
25
26 random_bytes (buf, sizeof buf);
27 quiet = true;
28 for (ofs = 0; ofs < BUF_SIZE; ofs += CHUNK_SIZE)
29 CHECK (write (fd, buf + ofs, CHUNK_SIZE) > 0,
30 "write %d bytes at offset %zu in \"%s\"",
31 (int) CHUNK_SIZE, ofs, file_name);
32 quiet = false;
33
34 wait_children (children, CHILD_CNT);
35}
diff --git a/tests/filesys/extended/syn-rw.ck b/tests/filesys/extended/syn-rw.ck
new file mode 100644
index 0000000..ac82aa8
--- /dev/null
+++ b/tests/filesys/extended/syn-rw.ck
@@ -0,0 +1,20 @@
1# -*- perl -*-
2use strict;
3use warnings;
4use tests::tests;
5use tests::random;
6check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']);
7(syn-rw) begin
8(syn-rw) create "logfile"
9(syn-rw) open "logfile"
10(syn-rw) exec child 1 of 4: "child-syn-rw 0"
11(syn-rw) exec child 2 of 4: "child-syn-rw 1"
12(syn-rw) exec child 3 of 4: "child-syn-rw 2"
13(syn-rw) exec child 4 of 4: "child-syn-rw 3"
14(syn-rw) wait for child 1 of 4 returned 0 (expected 0)
15(syn-rw) wait for child 2 of 4 returned 1 (expected 1)
16(syn-rw) wait for child 3 of 4 returned 2 (expected 2)
17(syn-rw) wait for child 4 of 4 returned 3 (expected 3)
18(syn-rw) end
19EOF
20pass;
diff --git a/tests/filesys/extended/syn-rw.h b/tests/filesys/extended/syn-rw.h
new file mode 100644
index 0000000..170aeb4
--- /dev/null
+++ b/tests/filesys/extended/syn-rw.h
@@ -0,0 +1,9 @@
1#ifndef TESTS_FILESYS_EXTENDED_SYN_RW_H
2#define TESTS_FILESYS_EXTENDED_SYN_RW_H
3
4#define CHUNK_SIZE 8
5#define CHUNK_CNT 512
6#define BUF_SIZE (CHUNK_SIZE * CHUNK_CNT)
7static const char file_name[] = "logfile";
8
9#endif /* tests/filesys/extended/syn-rw.h */
diff --git a/tests/filesys/extended/tar.c b/tests/filesys/extended/tar.c
new file mode 100644
index 0000000..9801484
--- /dev/null
+++ b/tests/filesys/extended/tar.c
@@ -0,0 +1,208 @@
1/* tar.c
2
3 Creates a tar archive. */
4
5#include <ustar.h>
6#include <syscall.h>
7#include <stdio.h>
8#include <string.h>
9
10static void usage (void);
11static bool make_tar_archive (const char *archive_name,
12 char *files[], size_t file_cnt);
13
14int
15main (int argc, char *argv[])
16{
17 if (argc < 3)
18 usage ();
19
20 return (make_tar_archive (argv[1], argv + 2, argc - 2)
21 ? EXIT_SUCCESS : EXIT_FAILURE);
22}
23
24static void
25usage (void)
26{
27 printf ("tar, tar archive creator\n"
28 "Usage: tar ARCHIVE FILE...\n"
29 "where ARCHIVE is the tar archive to create\n"
30 " and FILE... is a list of files or directories to put into it.\n"
31 "(ARCHIVE itself will not be included in the archive, even if it\n"
32 "is in a directory to be archived.)\n");
33 exit (EXIT_FAILURE);
34}
35
36static bool archive_file (char file_name[], size_t file_name_size,
37 int archive_fd, bool *write_error);
38
39static bool archive_ordinary_file (const char *file_name, int file_fd,
40 int archive_fd, bool *write_error);
41static bool archive_directory (char file_name[], size_t file_name_size,
42 int file_fd, int archive_fd, bool *write_error);
43static bool write_header (const char *file_name, enum ustar_type, int size,
44 int archive_fd, bool *write_error);
45
46static bool do_write (int fd, const char *buffer, int size, bool *write_error);
47
48static bool
49make_tar_archive (const char *archive_name, char *files[], size_t file_cnt)
50{
51 static const char zeros[512];
52 int archive_fd;
53 bool success = true;
54 bool write_error = false;
55 size_t i;
56
57 if (!create (archive_name, 0))
58 {
59 printf ("%s: create failed\n", archive_name);
60 return false;
61 }
62 archive_fd = open (archive_name);
63 if (archive_fd < 0)
64 {
65 printf ("%s: open failed\n", archive_name);
66 return false;
67 }
68
69 for (i = 0; i < file_cnt; i++)
70 {
71 char file_name[128];
72
73 strlcpy (file_name, files[i], sizeof file_name);
74 if (!archive_file (file_name, sizeof file_name,
75 archive_fd, &write_error))
76 success = false;
77 }
78
79 if (!do_write (archive_fd, zeros, 512, &write_error)
80 || !do_write (archive_fd, zeros, 512, &write_error))
81 success = false;
82
83 close (archive_fd);
84
85 return success;
86}
87
88static bool
89archive_file (char file_name[], size_t file_name_size,
90 int archive_fd, bool *write_error)
91{
92 int file_fd = open (file_name);
93 if (file_fd >= 0)
94 {
95 bool success;
96
97 if (inumber (file_fd) != inumber (archive_fd))
98 {
99 if (!isdir (file_fd))
100 success = archive_ordinary_file (file_name, file_fd,
101 archive_fd, write_error);
102 else
103 success = archive_directory (file_name, file_name_size, file_fd,
104 archive_fd, write_error);
105 }
106 else
107 {
108 /* Nothing to do: don't try to archive the archive file. */
109 success = true;
110 }
111
112 close (file_fd);
113
114 return success;
115 }
116 else
117 {
118 printf ("%s: open failed\n", file_name);
119 return false;
120 }
121}
122
123static bool
124archive_ordinary_file (const char *file_name, int file_fd,
125 int archive_fd, bool *write_error)
126{
127 bool read_error = false;
128 bool success = true;
129 int file_size = filesize (file_fd);
130
131 if (!write_header (file_name, USTAR_REGULAR, file_size,
132 archive_fd, write_error))
133 return false;
134
135 while (file_size > 0)
136 {
137 static char buf[512];
138 int chunk_size = file_size > 512 ? 512 : file_size;
139 int read_retval = read (file_fd, buf, chunk_size);
140 int bytes_read = read_retval > 0 ? read_retval : 0;
141
142 if (bytes_read != chunk_size && !read_error)
143 {
144 printf ("%s: read error\n", file_name);
145 read_error = true;
146 success = false;
147 }
148
149 memset (buf + bytes_read, 0, 512 - bytes_read);
150 if (!do_write (archive_fd, buf, 512, write_error))
151 success = false;
152
153 file_size -= chunk_size;
154 }
155
156 return success;
157}
158
159static bool
160archive_directory (char file_name[], size_t file_name_size, int file_fd,
161 int archive_fd, bool *write_error)
162{
163 size_t dir_len;
164 bool success = true;
165
166 dir_len = strlen (file_name);
167 if (dir_len + 1 + READDIR_MAX_LEN + 1 > file_name_size)
168 {
169 printf ("%s: file name too long\n", file_name);
170 return false;
171 }
172
173 if (!write_header (file_name, USTAR_DIRECTORY, 0, archive_fd, write_error))
174 return false;
175
176 file_name[dir_len] = '/';
177 while (readdir (file_fd, &file_name[dir_len + 1]))
178 if (!archive_file (file_name, file_name_size, archive_fd, write_error))
179 success = false;
180 file_name[dir_len] = '\0';
181
182 return success;
183}
184
185static bool
186write_header (const char *file_name, enum ustar_type type, int size,
187 int archive_fd, bool *write_error)
188{
189 static char header[512];
190 return (ustar_make_header (file_name, type, size, header)
191 && do_write (archive_fd, header, 512, write_error));
192}
193
194static bool
195do_write (int fd, const char *buffer, int size, bool *write_error)
196{
197 if (write (fd, buffer, size) == size)
198 return true;
199 else
200 {
201 if (!*write_error)
202 {
203 printf ("error writing archive\n");
204 *write_error = true;
205 }
206 return false;
207 }
208}