diff options
| author | Felipe Boeira <felipe.boeira@liu.se> | 2019-01-08 18:39:03 +0100 |
|---|---|---|
| committer | Felipe Boeira <felipe.boeira@liu.se> | 2019-01-08 18:39:03 +0100 |
| commit | d4522b8e9854178473adcea0fbb84f23f6e744bd (patch) | |
| tree | fbcf620617c5023154eba3f965b3a982daa64a47 /src/tests/filesys | |
| download | pintos-d4522b8e9854178473adcea0fbb84f23f6e744bd.tar.gz | |
Initial commit
Diffstat (limited to 'src/tests/filesys')
121 files changed, 2554 insertions, 0 deletions
diff --git a/src/tests/filesys/Grading.no-vm b/src/tests/filesys/Grading.no-vm new file mode 100644 index 0000000..ee98fc1 --- /dev/null +++ b/src/tests/filesys/Grading.no-vm @@ -0,0 +1,18 @@ +# Percentage of the testing point total designated for each set of +# tests. + +# This project is primarily about implementing the file system, but +# all the previous functionality should work too. It's not too easy +# to screw it up, thus the emphasis. + +# 65% for extended file system features. +30% tests/filesys/extended/Rubric.functionality +15% tests/filesys/extended/Rubric.robustness +20% tests/filesys/extended/Rubric.persistence + +# 20% to not break the provided file system features. +20% tests/filesys/base/Rubric + +# 15% for the rest. +10% tests/userprog/Rubric.functionality +5% tests/userprog/Rubric.robustness diff --git a/src/tests/filesys/Grading.with-vm b/src/tests/filesys/Grading.with-vm new file mode 100644 index 0000000..e7c041e --- /dev/null +++ b/src/tests/filesys/Grading.with-vm @@ -0,0 +1,22 @@ +# Percentage of the testing point total designated for each set of +# tests. + +# This project is primarily about implementing the file system, but +# all the previous functionality should work too. It's not too easy +# to screw it up, thus the emphasis. + +# 65% for extended file system features. +30% tests/filesys/extended/Rubric.functionality +15% tests/filesys/extended/Rubric.robustness +20% tests/filesys/extended/Rubric.persistence + +# 20% to not break the provided file system features. +20% tests/filesys/base/Rubric + +# 15% for the rest. +10% tests/userprog/Rubric.functionality +5% tests/userprog/Rubric.robustness + +# Up to 10% bonus for working VM functionality. +8% tests/vm/Rubric.functionality +2% tests/vm/Rubric.robustness diff --git a/src/tests/filesys/base/Make.tests b/src/tests/filesys/base/Make.tests new file mode 100644 index 0000000..e475222 --- /dev/null +++ b/src/tests/filesys/base/Make.tests @@ -0,0 +1,18 @@ +# -*- makefile -*- + +tests/filesys/base_TESTS = $(addprefix tests/filesys/base/,lg-create \ +lg-full lg-random lg-seq-block lg-seq-random sm-create sm-full \ +sm-random sm-seq-block sm-seq-random syn-read syn-remove syn-write) + +tests/filesys/base_PROGS = $(tests/filesys/base_TESTS) $(addprefix \ +tests/filesys/base/,child-syn-read child-syn-wrt) + +$(foreach prog,$(tests/filesys/base_PROGS), \ + $(eval $(prog)_SRC += $(prog).c tests/lib.c tests/filesys/seq-test.c)) +$(foreach prog,$(tests/filesys/base_TESTS), \ + $(eval $(prog)_SRC += tests/main.c)) + +tests/filesys/base/syn-read_PUTFILES = tests/filesys/base/child-syn-read +tests/filesys/base/syn-write_PUTFILES = tests/filesys/base/child-syn-wrt + +tests/filesys/base/syn-read.output: TIMEOUT = 300 diff --git a/src/tests/filesys/base/Rubric b/src/tests/filesys/base/Rubric new file mode 100644 index 0000000..49a9d15 --- /dev/null +++ b/src/tests/filesys/base/Rubric @@ -0,0 +1,19 @@ +Functionality of base file system: +- Test basic support for small files. +1 sm-create +2 sm-full +2 sm-random +2 sm-seq-block +3 sm-seq-random + +- Test basic support for large files. +1 lg-create +2 lg-full +2 lg-random +2 lg-seq-block +3 lg-seq-random + +- Test synchronized multiprogram access to files. +4 syn-read +4 syn-write +2 syn-remove diff --git a/src/tests/filesys/base/child-syn-read.c b/src/tests/filesys/base/child-syn-read.c new file mode 100644 index 0000000..77a5e26 --- /dev/null +++ b/src/tests/filesys/base/child-syn-read.c @@ -0,0 +1,44 @@ +/* Child process for syn-read test. + Reads the contents of a test file a byte at a time, in the + hope that this will take long enough that we can get a + significant amount of contention in the kernel file system + code. */ + +#include <random.h> +#include <stdio.h> +#include <stdlib.h> +#include <syscall.h> +#include "tests/lib.h" +#include "tests/filesys/base/syn-read.h" + +const char *test_name = "child-syn-read"; + +static char buf[BUF_SIZE]; + +int +main (int argc, const char *argv[]) +{ + int child_idx; + int fd; + size_t i; + + quiet = true; + + CHECK (argc == 2, "argc must be 2, actually %d", argc); + child_idx = atoi (argv[1]); + + random_init (0); + random_bytes (buf, sizeof buf); + + CHECK ((fd = open (file_name)) > 1, "open \"%s\"", file_name); + for (i = 0; i < sizeof buf; i++) + { + char c; + CHECK (read (fd, &c, 1) > 0, "read \"%s\"", file_name); + compare_bytes (&c, buf + i, 1, i, file_name); + } + close (fd); + + return child_idx; +} + diff --git a/src/tests/filesys/base/child-syn-wrt.c b/src/tests/filesys/base/child-syn-wrt.c new file mode 100644 index 0000000..1b52584 --- /dev/null +++ b/src/tests/filesys/base/child-syn-wrt.c @@ -0,0 +1,35 @@ +/* Child process for syn-read test. + Writes into part of a test file. Other processes will be + writing into other parts at the same time. */ + +#include <random.h> +#include <stdlib.h> +#include <syscall.h> +#include "tests/lib.h" +#include "tests/filesys/base/syn-write.h" + +char buf[BUF_SIZE]; + +int +main (int argc, char *argv[]) +{ + int child_idx; + int fd; + + quiet = true; + + CHECK (argc == 2, "argc must be 2, actually %d", argc); + child_idx = atoi (argv[1]); + + random_init (0); + random_bytes (buf, sizeof buf); + + CHECK ((fd = open (file_name)) > 1, "open \"%s\"", file_name); + seek (fd, CHUNK_SIZE * child_idx); + CHECK (write (fd, buf + CHUNK_SIZE * child_idx, CHUNK_SIZE) > 0, + "write \"%s\"", file_name); + msg ("close \"%s\"", file_name); + close (fd); + + return child_idx; +} diff --git a/src/tests/filesys/base/full.inc b/src/tests/filesys/base/full.inc new file mode 100644 index 0000000..38a0396 --- /dev/null +++ b/src/tests/filesys/base/full.inc @@ -0,0 +1,20 @@ +/* -*- c -*- */ + +#include "tests/filesys/seq-test.h" +#include "tests/main.h" + +static char buf[TEST_SIZE]; + +static size_t +return_test_size (void) +{ + return TEST_SIZE; +} + +void +test_main (void) +{ + seq_test ("quux", + buf, sizeof buf, sizeof buf, + return_test_size, NULL); +} diff --git a/src/tests/filesys/base/lg-create.c b/src/tests/filesys/base/lg-create.c new file mode 100644 index 0000000..5c45eee --- /dev/null +++ b/src/tests/filesys/base/lg-create.c @@ -0,0 +1,5 @@ +/* Tests that create properly zeros out the contents of a fairly + large file. */ + +#define TEST_SIZE 75678 +#include "tests/filesys/create.inc" diff --git a/src/tests/filesys/base/lg-create.ck b/src/tests/filesys/base/lg-create.ck new file mode 100644 index 0000000..86b2c51 --- /dev/null +++ b/src/tests/filesys/base/lg-create.ck @@ -0,0 +1,13 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); +(lg-create) begin +(lg-create) create "blargle" +(lg-create) open "blargle" for verification +(lg-create) verified contents of "blargle" +(lg-create) close "blargle" +(lg-create) end +EOF +pass; diff --git a/src/tests/filesys/base/lg-full.c b/src/tests/filesys/base/lg-full.c new file mode 100644 index 0000000..5f7234d --- /dev/null +++ b/src/tests/filesys/base/lg-full.c @@ -0,0 +1,6 @@ +/* Writes out the contents of a fairly large file all at once, + and then reads it back to make sure that it was written + properly. */ + +#define TEST_SIZE 75678 +#include "tests/filesys/base/full.inc" diff --git a/src/tests/filesys/base/lg-full.ck b/src/tests/filesys/base/lg-full.ck new file mode 100644 index 0000000..ee6c7f9 --- /dev/null +++ b/src/tests/filesys/base/lg-full.ck @@ -0,0 +1,16 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); +(lg-full) begin +(lg-full) create "quux" +(lg-full) open "quux" +(lg-full) writing "quux" +(lg-full) close "quux" +(lg-full) open "quux" for verification +(lg-full) verified contents of "quux" +(lg-full) close "quux" +(lg-full) end +EOF +pass; diff --git a/src/tests/filesys/base/lg-random.c b/src/tests/filesys/base/lg-random.c new file mode 100644 index 0000000..b6f8873 --- /dev/null +++ b/src/tests/filesys/base/lg-random.c @@ -0,0 +1,7 @@ +/* Writes out the content of a fairly large file in random order, + then reads it back in random order to verify that it was + written properly. */ + +#define BLOCK_SIZE 512 +#define TEST_SIZE (512 * 150) +#include "tests/filesys/base/random.inc" diff --git a/src/tests/filesys/base/lg-random.ck b/src/tests/filesys/base/lg-random.ck new file mode 100644 index 0000000..dd9f1dd --- /dev/null +++ b/src/tests/filesys/base/lg-random.ck @@ -0,0 +1,14 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); +(lg-random) begin +(lg-random) create "bazzle" +(lg-random) open "bazzle" +(lg-random) write "bazzle" in random order +(lg-random) read "bazzle" in random order +(lg-random) close "bazzle" +(lg-random) end +EOF +pass; diff --git a/src/tests/filesys/base/lg-seq-block.c b/src/tests/filesys/base/lg-seq-block.c new file mode 100644 index 0000000..580c30b --- /dev/null +++ b/src/tests/filesys/base/lg-seq-block.c @@ -0,0 +1,7 @@ +/* Writes out a fairly large file sequentially, one fixed-size + block at a time, then reads it back to verify that it was + written properly. */ + +#define TEST_SIZE 75678 +#define BLOCK_SIZE 513 +#include "tests/filesys/base/seq-block.inc" diff --git a/src/tests/filesys/base/lg-seq-block.ck b/src/tests/filesys/base/lg-seq-block.ck new file mode 100644 index 0000000..b789081 --- /dev/null +++ b/src/tests/filesys/base/lg-seq-block.ck @@ -0,0 +1,16 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); +(lg-seq-block) begin +(lg-seq-block) create "noodle" +(lg-seq-block) open "noodle" +(lg-seq-block) writing "noodle" +(lg-seq-block) close "noodle" +(lg-seq-block) open "noodle" for verification +(lg-seq-block) verified contents of "noodle" +(lg-seq-block) close "noodle" +(lg-seq-block) end +EOF +pass; diff --git a/src/tests/filesys/base/lg-seq-random.c b/src/tests/filesys/base/lg-seq-random.c new file mode 100644 index 0000000..fbb6bba --- /dev/null +++ b/src/tests/filesys/base/lg-seq-random.c @@ -0,0 +1,6 @@ +/* Writes out a fairly large file sequentially, one random-sized + block at a time, then reads it back to verify that it was + written properly. */ + +#define TEST_SIZE 75678 +#include "tests/filesys/base/seq-random.inc" diff --git a/src/tests/filesys/base/lg-seq-random.ck b/src/tests/filesys/base/lg-seq-random.ck new file mode 100644 index 0000000..6b2dc82 --- /dev/null +++ b/src/tests/filesys/base/lg-seq-random.ck @@ -0,0 +1,16 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); +(lg-seq-random) begin +(lg-seq-random) create "nibble" +(lg-seq-random) open "nibble" +(lg-seq-random) writing "nibble" +(lg-seq-random) close "nibble" +(lg-seq-random) open "nibble" for verification +(lg-seq-random) verified contents of "nibble" +(lg-seq-random) close "nibble" +(lg-seq-random) end +EOF +pass; diff --git a/src/tests/filesys/base/random.inc b/src/tests/filesys/base/random.inc new file mode 100644 index 0000000..eeeea68 --- /dev/null +++ b/src/tests/filesys/base/random.inc @@ -0,0 +1,59 @@ +/* -*- c -*- */ + +#include <random.h> +#include <stdio.h> +#include <string.h> +#include <syscall.h> +#include "tests/lib.h" +#include "tests/main.h" + +#if TEST_SIZE % BLOCK_SIZE != 0 +#error TEST_SIZE must be a multiple of BLOCK_SIZE +#endif + +#define BLOCK_CNT (TEST_SIZE / BLOCK_SIZE) + +char buf[TEST_SIZE]; +int order[BLOCK_CNT]; + +void +test_main (void) +{ + const char *file_name = "bazzle"; + int fd; + size_t i; + + random_init (57); + random_bytes (buf, sizeof buf); + + for (i = 0; i < BLOCK_CNT; i++) + order[i] = i; + + CHECK (create (file_name, TEST_SIZE), "create \"%s\"", file_name); + CHECK ((fd = open (file_name)) > 1, "open \"%s\"", file_name); + + msg ("write \"%s\" in random order", file_name); + shuffle (order, BLOCK_CNT, sizeof *order); + for (i = 0; i < BLOCK_CNT; i++) + { + size_t ofs = BLOCK_SIZE * order[i]; + seek (fd, ofs); + if (write (fd, buf + ofs, BLOCK_SIZE) != BLOCK_SIZE) + fail ("write %d bytes at offset %zu failed", (int) BLOCK_SIZE, ofs); + } + + msg ("read \"%s\" in random order", file_name); + shuffle (order, BLOCK_CNT, sizeof *order); + for (i = 0; i < BLOCK_CNT; i++) + { + char block[BLOCK_SIZE]; + size_t ofs = BLOCK_SIZE * order[i]; + seek (fd, ofs); + if (read (fd, block, BLOCK_SIZE) != BLOCK_SIZE) + fail ("read %d bytes at offset %zu failed", (int) BLOCK_SIZE, ofs); + compare_bytes (block, buf + ofs, BLOCK_SIZE, ofs, file_name); + } + + msg ("close \"%s\"", file_name); + close (fd); +} diff --git a/src/tests/filesys/base/seq-block.inc b/src/tests/filesys/base/seq-block.inc new file mode 100644 index 0000000..d4c1f57 --- /dev/null +++ b/src/tests/filesys/base/seq-block.inc @@ -0,0 +1,20 @@ +/* -*- c -*- */ + +#include "tests/filesys/seq-test.h" +#include "tests/main.h" + +static char buf[TEST_SIZE]; + +static size_t +return_block_size (void) +{ + return BLOCK_SIZE; +} + +void +test_main (void) +{ + seq_test ("noodle", + buf, sizeof buf, sizeof buf, + return_block_size, NULL); +} diff --git a/src/tests/filesys/base/seq-random.inc b/src/tests/filesys/base/seq-random.inc new file mode 100644 index 0000000..a4da4c5 --- /dev/null +++ b/src/tests/filesys/base/seq-random.inc @@ -0,0 +1,22 @@ +/* -*- c -*- */ + +#include <random.h> +#include "tests/filesys/seq-test.h" +#include "tests/main.h" + +static char buf[TEST_SIZE]; + +static size_t +return_random (void) +{ + return random_ulong () % 1031 + 1; +} + +void +test_main (void) +{ + random_init (-1); + seq_test ("nibble", + buf, sizeof buf, sizeof buf, + return_random, NULL); +} diff --git a/src/tests/filesys/base/sm-create.c b/src/tests/filesys/base/sm-create.c new file mode 100644 index 0000000..6b97ac1 --- /dev/null +++ b/src/tests/filesys/base/sm-create.c @@ -0,0 +1,5 @@ +/* Tests that create properly zeros out the contents of a fairly + small file. */ + +#define TEST_SIZE 5678 +#include "tests/filesys/create.inc" diff --git a/src/tests/filesys/base/sm-create.ck b/src/tests/filesys/base/sm-create.ck new file mode 100644 index 0000000..8ca80dc --- /dev/null +++ b/src/tests/filesys/base/sm-create.ck @@ -0,0 +1,13 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); +(sm-create) begin +(sm-create) create "blargle" +(sm-create) open "blargle" for verification +(sm-create) verified contents of "blargle" +(sm-create) close "blargle" +(sm-create) end +EOF +pass; diff --git a/src/tests/filesys/base/sm-full.c b/src/tests/filesys/base/sm-full.c new file mode 100644 index 0000000..23ff3d4 --- /dev/null +++ b/src/tests/filesys/base/sm-full.c @@ -0,0 +1,6 @@ +/* Writes out the contents of a fairly small file all at once, + and then reads it back to make sure that it was written + properly. */ + +#define TEST_SIZE 5678 +#include "tests/filesys/base/full.inc" diff --git a/src/tests/filesys/base/sm-full.ck b/src/tests/filesys/base/sm-full.ck new file mode 100644 index 0000000..2e0eb36 --- /dev/null +++ b/src/tests/filesys/base/sm-full.ck @@ -0,0 +1,16 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); +(sm-full) begin +(sm-full) create "quux" +(sm-full) open "quux" +(sm-full) writing "quux" +(sm-full) close "quux" +(sm-full) open "quux" for verification +(sm-full) verified contents of "quux" +(sm-full) close "quux" +(sm-full) end +EOF +pass; diff --git a/src/tests/filesys/base/sm-random.c b/src/tests/filesys/base/sm-random.c new file mode 100644 index 0000000..42d670f --- /dev/null +++ b/src/tests/filesys/base/sm-random.c @@ -0,0 +1,7 @@ +/* Writes out the content of a fairly small file in random order, + then reads it back in random order to verify that it was + written properly. */ + +#define BLOCK_SIZE 13 +#define TEST_SIZE (13 * 123) +#include "tests/filesys/base/random.inc" diff --git a/src/tests/filesys/base/sm-random.ck b/src/tests/filesys/base/sm-random.ck new file mode 100644 index 0000000..bda049d --- /dev/null +++ b/src/tests/filesys/base/sm-random.ck @@ -0,0 +1,14 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); +(sm-random) begin +(sm-random) create "bazzle" +(sm-random) open "bazzle" +(sm-random) write "bazzle" in random order +(sm-random) read "bazzle" in random order +(sm-random) close "bazzle" +(sm-random) end +EOF +pass; diff --git a/src/tests/filesys/base/sm-seq-block.c b/src/tests/filesys/base/sm-seq-block.c new file mode 100644 index 0000000..e368327 --- /dev/null +++ b/src/tests/filesys/base/sm-seq-block.c @@ -0,0 +1,7 @@ +/* Writes out a fairly small file sequentially, one fixed-size + block at a time, then reads it back to verify that it was + written properly. */ + +#define TEST_SIZE 5678 +#define BLOCK_SIZE 513 +#include "tests/filesys/base/seq-block.inc" diff --git a/src/tests/filesys/base/sm-seq-block.ck b/src/tests/filesys/base/sm-seq-block.ck new file mode 100644 index 0000000..0e2939d --- /dev/null +++ b/src/tests/filesys/base/sm-seq-block.ck @@ -0,0 +1,16 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); +(sm-seq-block) begin +(sm-seq-block) create "noodle" +(sm-seq-block) open "noodle" +(sm-seq-block) writing "noodle" +(sm-seq-block) close "noodle" +(sm-seq-block) open "noodle" for verification +(sm-seq-block) verified contents of "noodle" +(sm-seq-block) close "noodle" +(sm-seq-block) end +EOF +pass; diff --git a/src/tests/filesys/base/sm-seq-random.c b/src/tests/filesys/base/sm-seq-random.c new file mode 100644 index 0000000..89e5b71 --- /dev/null +++ b/src/tests/filesys/base/sm-seq-random.c @@ -0,0 +1,6 @@ +/* Writes out a fairly large file sequentially, one random-sized + block at a time, then reads it back to verify that it was + written properly. */ + +#define TEST_SIZE 5678 +#include "tests/filesys/base/seq-random.inc" diff --git a/src/tests/filesys/base/sm-seq-random.ck b/src/tests/filesys/base/sm-seq-random.ck new file mode 100644 index 0000000..2fb368b --- /dev/null +++ b/src/tests/filesys/base/sm-seq-random.ck @@ -0,0 +1,16 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); +(sm-seq-random) begin +(sm-seq-random) create "nibble" +(sm-seq-random) open "nibble" +(sm-seq-random) writing "nibble" +(sm-seq-random) close "nibble" +(sm-seq-random) open "nibble" for verification +(sm-seq-random) verified contents of "nibble" +(sm-seq-random) close "nibble" +(sm-seq-random) end +EOF +pass; diff --git a/src/tests/filesys/base/syn-read.c b/src/tests/filesys/base/syn-read.c new file mode 100644 index 0000000..7c36a42 --- /dev/null +++ b/src/tests/filesys/base/syn-read.c @@ -0,0 +1,31 @@ +/* Spawns 10 child processes, all of which read from the same + file and make sure that the contents are what they should + be. */ + +#include <random.h> +#include <stdio.h> +#include <syscall.h> +#include "tests/lib.h" +#include "tests/main.h" +#include "tests/filesys/base/syn-read.h" + +static char buf[BUF_SIZE]; + +#define CHILD_CNT 10 + +void +test_main (void) +{ + pid_t children[CHILD_CNT]; + int fd; + + CHECK (create (file_name, sizeof buf), "create \"%s\"", file_name); + CHECK ((fd = open (file_name)) > 1, "open \"%s\"", file_name); + random_bytes (buf, sizeof buf); + CHECK (write (fd, buf, sizeof buf) > 0, "write \"%s\"", file_name); + msg ("close \"%s\"", file_name); + close (fd); + + exec_children ("child-syn-read", children, CHILD_CNT); + wait_children (children, CHILD_CNT); +} diff --git a/src/tests/filesys/base/syn-read.ck b/src/tests/filesys/base/syn-read.ck new file mode 100644 index 0000000..e2f68e8 --- /dev/null +++ b/src/tests/filesys/base/syn-read.ck @@ -0,0 +1,33 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); +(syn-read) begin +(syn-read) create "data" +(syn-read) open "data" +(syn-read) write "data" +(syn-read) close "data" +(syn-read) exec child 1 of 10: "child-syn-read 0" +(syn-read) exec child 2 of 10: "child-syn-read 1" +(syn-read) exec child 3 of 10: "child-syn-read 2" +(syn-read) exec child 4 of 10: "child-syn-read 3" +(syn-read) exec child 5 of 10: "child-syn-read 4" +(syn-read) exec child 6 of 10: "child-syn-read 5" +(syn-read) exec child 7 of 10: "child-syn-read 6" +(syn-read) exec child 8 of 10: "child-syn-read 7" +(syn-read) exec child 9 of 10: "child-syn-read 8" +(syn-read) exec child 10 of 10: "child-syn-read 9" +(syn-read) wait for child 1 of 10 returned 0 (expected 0) +(syn-read) wait for child 2 of 10 returned 1 (expected 1) +(syn-read) wait for child 3 of 10 returned 2 (expected 2) +(syn-read) wait for child 4 of 10 returned 3 (expected 3) +(syn-read) wait for child 5 of 10 returned 4 (expected 4) +(syn-read) wait for child 6 of 10 returned 5 (expected 5) +(syn-read) wait for child 7 of 10 returned 6 (expected 6) +(syn-read) wait for child 8 of 10 returned 7 (expected 7) +(syn-read) wait for child 9 of 10 returned 8 (expected 8) +(syn-read) wait for child 10 of 10 returned 9 (expected 9) +(syn-read) end +EOF +pass; diff --git a/src/tests/filesys/base/syn-read.h b/src/tests/filesys/base/syn-read.h new file mode 100644 index 0000000..bff8082 --- /dev/null +++ b/src/tests/filesys/base/syn-read.h @@ -0,0 +1,7 @@ +#ifndef TESTS_FILESYS_BASE_SYN_READ_H +#define TESTS_FILESYS_BASE_SYN_READ_H + +#define BUF_SIZE 1024 +static const char file_name[] = "data"; + +#endif /* tests/filesys/base/syn-read.h */ diff --git a/src/tests/filesys/base/syn-remove.c b/src/tests/filesys/base/syn-remove.c new file mode 100644 index 0000000..c9ba110 --- /dev/null +++ b/src/tests/filesys/base/syn-remove.c @@ -0,0 +1,30 @@ +/* Verifies that a deleted file may still be written to and read + from. */ + +#include <random.h> +#include <string.h> +#include <syscall.h> +#include "tests/lib.h" +#include "tests/main.h" + +char buf1[1234]; +char buf2[1234]; + +void +test_main (void) +{ + const char *file_name = "deleteme"; + int fd; + + CHECK (create (file_name, sizeof buf1), "create \"%s\"", file_name); + CHECK ((fd = open (file_name)) > 1, "open \"%s\"", file_name); + CHECK (remove (file_name), "remove \"%s\"", file_name); + random_bytes (buf1, sizeof buf1); + CHECK (write (fd, buf1, sizeof buf1) > 0, "write \"%s\"", file_name); + msg ("seek \"%s\" to 0", file_name); + seek (fd, 0); + CHECK (read (fd, buf2, sizeof buf2) > 0, "read \"%s\"", file_name); + compare_bytes (buf2, buf1, sizeof buf1, 0, file_name); + msg ("close \"%s\"", file_name); + close (fd); +} diff --git a/src/tests/filesys/base/syn-remove.ck b/src/tests/filesys/base/syn-remove.ck new file mode 100644 index 0000000..16ff11e --- /dev/null +++ b/src/tests/filesys/base/syn-remove.ck @@ -0,0 +1,16 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); +(syn-remove) begin +(syn-remove) create "deleteme" +(syn-remove) open "deleteme" +(syn-remove) remove "deleteme" +(syn-remove) write "deleteme" +(syn-remove) seek "deleteme" to 0 +(syn-remove) read "deleteme" +(syn-remove) close "deleteme" +(syn-remove) end +EOF +pass; diff --git a/src/tests/filesys/base/syn-write.c b/src/tests/filesys/base/syn-write.c new file mode 100644 index 0000000..1439862 --- /dev/null +++ b/src/tests/filesys/base/syn-write.c @@ -0,0 +1,31 @@ +/* Spawns several child processes to write out different parts of + the contents of a file and waits for them to finish. Then + reads back the file and verifies its contents. */ + +#include <random.h> +#include <stdio.h> +#include <string.h> +#include <syscall.h> +#include "tests/filesys/base/syn-write.h" +#include "tests/lib.h" +#include "tests/main.h" + +char buf1[BUF_SIZE]; +char buf2[BUF_SIZE]; + +void +test_main (void) +{ + pid_t children[CHILD_CNT]; + int fd; + + CHECK (create (file_name, sizeof buf1), "create \"%s\"", file_name); + + exec_children ("child-syn-wrt", children, CHILD_CNT); + wait_children (children, CHILD_CNT); + + CHECK ((fd = open (file_name)) > 1, "open \"%s\"", file_name); + CHECK (read (fd, buf1, sizeof buf1) > 0, "read \"%s\"", file_name); + random_bytes (buf2, sizeof buf2); + compare_bytes (buf1, buf2, sizeof buf1, 0, file_name); +} diff --git a/src/tests/filesys/base/syn-write.ck b/src/tests/filesys/base/syn-write.ck new file mode 100644 index 0000000..629a7a2 --- /dev/null +++ b/src/tests/filesys/base/syn-write.ck @@ -0,0 +1,32 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); +(syn-write) begin +(syn-write) create "stuff" +(syn-write) exec child 1 of 10: "child-syn-wrt 0" +(syn-write) exec child 2 of 10: "child-syn-wrt 1" +(syn-write) exec child 3 of 10: "child-syn-wrt 2" +(syn-write) exec child 4 of 10: "child-syn-wrt 3" +(syn-write) exec child 5 of 10: "child-syn-wrt 4" +(syn-write) exec child 6 of 10: "child-syn-wrt 5" +(syn-write) exec child 7 of 10: "child-syn-wrt 6" +(syn-write) exec child 8 of 10: "child-syn-wrt 7" +(syn-write) exec child 9 of 10: "child-syn-wrt 8" +(syn-write) exec child 10 of 10: "child-syn-wrt 9" +(syn-write) wait for child 1 of 10 returned 0 (expected 0) +(syn-write) wait for child 2 of 10 returned 1 (expected 1) +(syn-write) wait for child 3 of 10 returned 2 (expected 2) +(syn-write) wait for child 4 of 10 returned 3 (expected 3) +(syn-write) wait for child 5 of 10 returned 4 (expected 4) +(syn-write) wait for child 6 of 10 returned 5 (expected 5) +(syn-write) wait for child 7 of 10 returned 6 (expected 6) +(syn-write) wait for child 8 of 10 returned 7 (expected 7) +(syn-write) wait for child 9 of 10 returned 8 (expected 8) +(syn-write) wait for child 10 of 10 returned 9 (expected 9) +(syn-write) open "stuff" +(syn-write) read "stuff" +(syn-write) end +EOF +pass; diff --git a/src/tests/filesys/base/syn-write.h b/src/tests/filesys/base/syn-write.h new file mode 100644 index 0000000..07a6d5a --- /dev/null +++ b/src/tests/filesys/base/syn-write.h @@ -0,0 +1,9 @@ +#ifndef TESTS_FILESYS_BASE_SYN_WRITE_H +#define TESTS_FILESYS_BASE_SYN_WRITE_H + +#define CHILD_CNT 10 +#define CHUNK_SIZE 512 +#define BUF_SIZE (CHILD_CNT * CHUNK_SIZE) +static const char file_name[] = "stuff"; + +#endif /* tests/filesys/base/syn-write.h */ diff --git a/src/tests/filesys/create.inc b/src/tests/filesys/create.inc new file mode 100644 index 0000000..4baf771 --- /dev/null +++ b/src/tests/filesys/create.inc @@ -0,0 +1,15 @@ +/* -*- c -*- */ + +#include <syscall.h> +#include "tests/lib.h" +#include "tests/main.h" + +static char buf[TEST_SIZE]; + +void +test_main (void) +{ + const char *file_name = "blargle"; + CHECK (create (file_name, TEST_SIZE), "create \"%s\"", file_name); + check_file (file_name, buf, TEST_SIZE); +} diff --git a/src/tests/filesys/extended/Make.tests b/src/tests/filesys/extended/Make.tests new file mode 100644 index 0000000..75a872b --- /dev/null +++ b/src/tests/filesys/extended/Make.tests @@ -0,0 +1,61 @@ +# -*- makefile -*- + +raw_tests = 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_TESTS = $(patsubst %,tests/filesys/extended/%,$(raw_tests)) +tests/filesys/extended_EXTRA_GRADES = $(patsubst %,tests/filesys/extended/%-persistence,$(raw_tests)) + +tests/filesys/extended_PROGS = $(tests/filesys/extended_TESTS) \ +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)) +# The version of GNU make 3.80 on vine barfs if this is split at +# the last comma. +$(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/dir-vine.output: TIMEOUT = 150 + +GETTIMEOUT = 60 + +GETCMD = pintos -v -k -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 += < /dev/null +GETCMD += 2> $(TEST)-persistence.errors $(if $(VERBOSE),|tee,>) $(TEST)-persistence.output + +tests/filesys/extended/%.output: os.dsk + rm -f tmp.dsk + pintos-mkdisk tmp.dsk 2 + $(TESTCMD) + $(GETCMD) + rm -f tmp.dsk +$(foreach raw_test,$(raw_tests),$(eval tests/filesys/extended/$(raw_test)-persistence.output: tests/filesys/extended/$(raw_test).output)) +$(foreach raw_test,$(raw_tests),$(eval tests/filesys/extended/$(raw_test)-persistence.result: tests/filesys/extended/$(raw_test).result)) + +TARS = $(addsuffix .tar,$(tests/filesys/extended_TESTS)) + +clean:: + rm -f $(TARS) + rm -f tests/filesys/extended/can-rmdir-cwd diff --git a/src/tests/filesys/extended/Rubric.functionality b/src/tests/filesys/extended/Rubric.functionality new file mode 100644 index 0000000..91ed6f0 --- /dev/null +++ b/src/tests/filesys/extended/Rubric.functionality @@ -0,0 +1,26 @@ +Functionality of extended file system: +- Test directory support. +1 dir-mkdir +3 dir-mk-tree + +1 dir-rmdir +3 dir-rm-tree + +5 dir-vine + +- Test file growth. +1 grow-create +1 grow-seq-sm +3 grow-seq-lg +3 grow-sparse +3 grow-two-files +1 grow-tell +1 grow-file-size + +- Test directory growth. +1 grow-dir-lg +1 grow-root-sm +1 grow-root-lg + +- Test writing from multiple processes. +5 syn-rw diff --git a/src/tests/filesys/extended/Rubric.persistence b/src/tests/filesys/extended/Rubric.persistence new file mode 100644 index 0000000..405620a --- /dev/null +++ b/src/tests/filesys/extended/Rubric.persistence @@ -0,0 +1,24 @@ +Persistence of file system: +1 dir-empty-name-persistence +1 dir-mk-tree-persistence +1 dir-mkdir-persistence +1 dir-open-persistence +1 dir-over-file-persistence +1 dir-rm-cwd-persistence +1 dir-rm-parent-persistence +1 dir-rm-root-persistence +1 dir-rm-tree-persistence +1 dir-rmdir-persistence +1 dir-under-file-persistence +1 dir-vine-persistence +1 grow-create-persistence +1 grow-dir-lg-persistence +1 grow-file-size-persistence +1 grow-root-lg-persistence +1 grow-root-sm-persistence +1 grow-seq-lg-persistence +1 grow-seq-sm-persistence +1 grow-sparse-persistence +1 grow-tell-persistence +1 grow-two-files-persistence +1 syn-rw-persistence diff --git a/src/tests/filesys/extended/Rubric.robustness b/src/tests/filesys/extended/Rubric.robustness new file mode 100644 index 0000000..fb9f32f --- /dev/null +++ b/src/tests/filesys/extended/Rubric.robustness @@ -0,0 +1,9 @@ +Robustness of file system: +1 dir-empty-name +1 dir-open +1 dir-over-file +1 dir-under-file + +3 dir-rm-cwd +2 dir-rm-parent +1 dir-rm-root diff --git a/src/tests/filesys/extended/child-syn-rw.c b/src/tests/filesys/extended/child-syn-rw.c new file mode 100644 index 0000000..0e2217d --- /dev/null +++ b/src/tests/filesys/extended/child-syn-rw.c @@ -0,0 +1,53 @@ +/* Child process for syn-rw. + Reads from a file created by our parent process, which is + growing it. We loop until we've read the whole file + successfully. Many iterations through the loop will return 0 + bytes, because the file has not grown in the meantime. That + is, we are "busy waiting" for the file to grow. + (This test could be improved by adding a "yield" system call + and calling yield whenever we receive a 0-byte read.) */ + +#include <random.h> +#include <stdlib.h> +#include <syscall.h> +#include "tests/filesys/extended/syn-rw.h" +#include "tests/lib.h" + +const char *test_name = "child-syn-rw"; + +static char buf1[BUF_SIZE]; +static char buf2[BUF_SIZE]; + +int +main (int argc, const char *argv[]) +{ + int child_idx; + int fd; + size_t ofs; + + quiet = true; + + CHECK (argc == 2, "argc must be 2, actually %d", argc); + child_idx = atoi (argv[1]); + + random_init (0); + random_bytes (buf1, sizeof buf1); + + CHECK ((fd = open (file_name)) > 1, "open \"%s\"", file_name); + ofs = 0; + while (ofs < sizeof buf2) + { + int bytes_read = read (fd, buf2 + ofs, sizeof buf2 - ofs); + CHECK (bytes_read >= -1 && bytes_read <= (int) (sizeof buf2 - ofs), + "%zu-byte read on \"%s\" returned invalid value of %d", + sizeof buf2 - ofs, file_name, bytes_read); + if (bytes_read > 0) + { + compare_bytes (buf2 + ofs, buf1 + ofs, bytes_read, ofs, file_name); + ofs += bytes_read; + } + } + close (fd); + + return child_idx; +} diff --git a/src/tests/filesys/extended/dir-empty-name-persistence.ck b/src/tests/filesys/extended/dir-empty-name-persistence.ck new file mode 100644 index 0000000..562c451 --- /dev/null +++ b/src/tests/filesys/extended/dir-empty-name-persistence.ck @@ -0,0 +1,6 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_archive ({}); +pass; diff --git a/src/tests/filesys/extended/dir-empty-name.c b/src/tests/filesys/extended/dir-empty-name.c new file mode 100644 index 0000000..c4859d2 --- /dev/null +++ b/src/tests/filesys/extended/dir-empty-name.c @@ -0,0 +1,12 @@ +/* Tries to create a directory named as the empty string, + which must return failure. */ + +#include <syscall.h> +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + CHECK (!mkdir (""), "mkdir \"\" (must return false)"); +} diff --git a/src/tests/filesys/extended/dir-empty-name.ck b/src/tests/filesys/extended/dir-empty-name.ck new file mode 100644 index 0000000..d6c5621 --- /dev/null +++ b/src/tests/filesys/extended/dir-empty-name.ck @@ -0,0 +1,10 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); +(dir-empty-name) begin +(dir-empty-name) mkdir "" (must return false) +(dir-empty-name) end +EOF +pass; diff --git a/src/tests/filesys/extended/dir-mk-tree-persistence.ck b/src/tests/filesys/extended/dir-mk-tree-persistence.ck new file mode 100644 index 0000000..fb16afd --- /dev/null +++ b/src/tests/filesys/extended/dir-mk-tree-persistence.ck @@ -0,0 +1,16 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +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-tree.c b/src/tests/filesys/extended/dir-mk-tree.c new file mode 100644 index 0000000..a714ff3 --- /dev/null +++ b/src/tests/filesys/extended/dir-mk-tree.c @@ -0,0 +1,12 @@ +/* Creates directories /0/0/0 through /3/2/2 and creates files in + the leaf directories. */ + +#include "tests/filesys/extended/mk-tree.h" +#include "tests/main.h" + +void +test_main (void) +{ + make_tree (4, 3, 3, 4); +} + diff --git a/src/tests/filesys/extended/dir-mk-tree.ck b/src/tests/filesys/extended/dir-mk-tree.ck new file mode 100644 index 0000000..a8507e2 --- /dev/null +++ b/src/tests/filesys/extended/dir-mk-tree.ck @@ -0,0 +1,12 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); +(dir-mk-tree) begin +(dir-mk-tree) creating /0/0/0/0 through /3/2/2/3... +(dir-mk-tree) open "/0/2/0/3" +(dir-mk-tree) close "/0/2/0/3" +(dir-mk-tree) end +EOF +pass; diff --git a/src/tests/filesys/extended/dir-mkdir-persistence.ck b/src/tests/filesys/extended/dir-mkdir-persistence.ck new file mode 100644 index 0000000..7682900 --- /dev/null +++ b/src/tests/filesys/extended/dir-mkdir-persistence.ck @@ -0,0 +1,6 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_archive ({'a' => {'b' => ["\0" x 512]}}); +pass; diff --git a/src/tests/filesys/extended/dir-mkdir.c b/src/tests/filesys/extended/dir-mkdir.c new file mode 100644 index 0000000..994f41c --- /dev/null +++ b/src/tests/filesys/extended/dir-mkdir.c @@ -0,0 +1,15 @@ +/* Tests mkdir(). */ + +#include <syscall.h> +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + CHECK (mkdir ("a"), "mkdir \"a\""); + CHECK (create ("a/b", 512), "create \"a/b\""); + CHECK (chdir ("a"), "chdir \"a\""); + CHECK (open ("b") > 1, "open \"b\""); +} + diff --git a/src/tests/filesys/extended/dir-mkdir.ck b/src/tests/filesys/extended/dir-mkdir.ck new file mode 100644 index 0000000..4644f80 --- /dev/null +++ b/src/tests/filesys/extended/dir-mkdir.ck @@ -0,0 +1,13 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); +(dir-mkdir) begin +(dir-mkdir) mkdir "a" +(dir-mkdir) create "a/b" +(dir-mkdir) chdir "a" +(dir-mkdir) open "b" +(dir-mkdir) end +EOF +pass; diff --git a/src/tests/filesys/extended/dir-open-persistence.ck b/src/tests/filesys/extended/dir-open-persistence.ck new file mode 100644 index 0000000..26ff2f1 --- /dev/null +++ b/src/tests/filesys/extended/dir-open-persistence.ck @@ -0,0 +1,6 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_archive ({"xyzzy" => {}}); +pass; diff --git a/src/tests/filesys/extended/dir-open.c b/src/tests/filesys/extended/dir-open.c new file mode 100644 index 0000000..29d18b8 --- /dev/null +++ b/src/tests/filesys/extended/dir-open.c @@ -0,0 +1,21 @@ +/* Opens a directory, then tries to write to it, which must + fail. */ + +#include <syscall.h> +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + int fd; + int retval; + + CHECK (mkdir ("xyzzy"), "mkdir \"xyzzy\""); + CHECK ((fd = open ("xyzzy")) > 1, "open \"xyzzy\""); + + msg ("write \"xyzzy\""); + retval = write (fd, "foobar", 6); + CHECK (retval == -1, + "write \"xyzzy\" (must return -1, actually %d)", retval); +} diff --git a/src/tests/filesys/extended/dir-open.ck b/src/tests/filesys/extended/dir-open.ck new file mode 100644 index 0000000..fccc563 --- /dev/null +++ b/src/tests/filesys/extended/dir-open.ck @@ -0,0 +1,20 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected ([<<'EOF', <<'EOF']); +(dir-open) begin +(dir-open) mkdir "xyzzy" +(dir-open) open "xyzzy" +(dir-open) write "xyzzy" +(dir-open) write "xyzzy" (must return -1, actually -1) +(dir-open) end +dir-open: exit(0) +EOF +(dir-open) begin +(dir-open) mkdir "xyzzy" +(dir-open) open "xyzzy" +(dir-open) write "xyzzy" +dir-open: exit(-1) +EOF +pass; diff --git a/src/tests/filesys/extended/dir-over-file-persistence.ck b/src/tests/filesys/extended/dir-over-file-persistence.ck new file mode 100644 index 0000000..56b4ed2 --- /dev/null +++ b/src/tests/filesys/extended/dir-over-file-persistence.ck @@ -0,0 +1,6 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_archive ({"abc" => {}}); +pass; diff --git a/src/tests/filesys/extended/dir-over-file.c b/src/tests/filesys/extended/dir-over-file.c new file mode 100644 index 0000000..cdd2c62 --- /dev/null +++ b/src/tests/filesys/extended/dir-over-file.c @@ -0,0 +1,13 @@ +/* Tries to create a file with the same name as an existing + directory, which must return failure. */ + +#include <syscall.h> +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + CHECK (mkdir ("abc"), "mkdir \"abc\""); + CHECK (!create ("abc", 0), "create \"abc\" (must return false)"); +} diff --git a/src/tests/filesys/extended/dir-over-file.ck b/src/tests/filesys/extended/dir-over-file.ck new file mode 100644 index 0000000..aae1c1e --- /dev/null +++ b/src/tests/filesys/extended/dir-over-file.ck @@ -0,0 +1,11 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); +(dir-over-file) begin +(dir-over-file) mkdir "abc" +(dir-over-file) create "abc" (must return false) +(dir-over-file) end +EOF +pass; diff --git a/src/tests/filesys/extended/dir-rm-cwd-persistence.ck b/src/tests/filesys/extended/dir-rm-cwd-persistence.ck new file mode 100644 index 0000000..7533570 --- /dev/null +++ b/src/tests/filesys/extended/dir-rm-cwd-persistence.ck @@ -0,0 +1,8 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +my ($cwd_removable) = read_text_file ("tests/filesys/extended/can-rmdir-cwd"); +$cwd_removable eq 'YES' || $cwd_removable eq 'NO' or die; +check_archive ($cwd_removable eq 'YES' ? {} : {"a" => {}}); +pass; diff --git a/src/tests/filesys/extended/dir-rm-cwd.c b/src/tests/filesys/extended/dir-rm-cwd.c new file mode 100644 index 0000000..78e13de --- /dev/null +++ b/src/tests/filesys/extended/dir-rm-cwd.c @@ -0,0 +1,75 @@ +/* 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 ("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"); +} diff --git a/src/tests/filesys/extended/dir-rm-cwd.ck b/src/tests/filesys/extended/dir-rm-cwd.ck new file mode 100644 index 0000000..6fa4739 --- /dev/null +++ b/src/tests/filesys/extended/dir-rm-cwd.ck @@ -0,0 +1,51 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +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) 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 +open (CAN_RMDIR_CWD, ">tests/filesys/extended/can-rmdir-cwd") + or die "tests/filesys/extended/can-rmdir-cwd: create: $!\n"; +print CAN_RMDIR_CWD "$cwd_removable"; +close (CAN_RMDIR_CWD); +pass; diff --git a/src/tests/filesys/extended/dir-rm-parent-persistence.ck b/src/tests/filesys/extended/dir-rm-parent-persistence.ck new file mode 100644 index 0000000..f30b04a --- /dev/null +++ b/src/tests/filesys/extended/dir-rm-parent-persistence.ck @@ -0,0 +1,6 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_archive ({"a" => {"b" => {}}}); +pass; diff --git a/src/tests/filesys/extended/dir-rm-parent.c b/src/tests/filesys/extended/dir-rm-parent.c new file mode 100644 index 0000000..eb43f5b --- /dev/null +++ b/src/tests/filesys/extended/dir-rm-parent.c @@ -0,0 +1,16 @@ +/* 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" +#include "tests/main.h" + +void +test_main (void) +{ + CHECK (mkdir ("a"), "mkdir \"a\""); + CHECK (chdir ("a"), "chdir \"a\""); + CHECK (mkdir ("b"), "mkdir \"b\""); + CHECK (chdir ("b"), "chdir \"b\""); + CHECK (!remove ("/a"), "remove \"/a\" (must fail)"); +} diff --git a/src/tests/filesys/extended/dir-rm-parent.ck b/src/tests/filesys/extended/dir-rm-parent.ck new file mode 100644 index 0000000..9fea8f2 --- /dev/null +++ b/src/tests/filesys/extended/dir-rm-parent.ck @@ -0,0 +1,14 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); +(dir-rm-parent) begin +(dir-rm-parent) mkdir "a" +(dir-rm-parent) chdir "a" +(dir-rm-parent) mkdir "b" +(dir-rm-parent) chdir "b" +(dir-rm-parent) remove "/a" (must fail) +(dir-rm-parent) end +EOF +pass; diff --git a/src/tests/filesys/extended/dir-rm-root-persistence.ck b/src/tests/filesys/extended/dir-rm-root-persistence.ck new file mode 100644 index 0000000..6315107 --- /dev/null +++ b/src/tests/filesys/extended/dir-rm-root-persistence.ck @@ -0,0 +1,6 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_archive ({"a" => ["\0" x 243]}); +pass; diff --git a/src/tests/filesys/extended/dir-rm-root.c b/src/tests/filesys/extended/dir-rm-root.c new file mode 100644 index 0000000..c47f1eb --- /dev/null +++ b/src/tests/filesys/extended/dir-rm-root.c @@ -0,0 +1,13 @@ +/* Try to remove the root directory. + This must fail. */ + +#include <syscall.h> +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + CHECK (!remove ("/"), "remove \"/\" (must fail)"); + CHECK (create ("/a", 243), "create \"/a\""); +} diff --git a/src/tests/filesys/extended/dir-rm-root.ck b/src/tests/filesys/extended/dir-rm-root.ck new file mode 100644 index 0000000..8a69ff3 --- /dev/null +++ b/src/tests/filesys/extended/dir-rm-root.ck @@ -0,0 +1,11 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); +(dir-rm-root) begin +(dir-rm-root) remove "/" (must fail) +(dir-rm-root) create "/a" +(dir-rm-root) end +EOF +pass; diff --git a/src/tests/filesys/extended/dir-rm-tree-persistence.ck b/src/tests/filesys/extended/dir-rm-tree-persistence.ck new file mode 100644 index 0000000..562c451 --- /dev/null +++ b/src/tests/filesys/extended/dir-rm-tree-persistence.ck @@ -0,0 +1,6 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_archive ({}); +pass; diff --git a/src/tests/filesys/extended/dir-rm-tree.c b/src/tests/filesys/extended/dir-rm-tree.c new file mode 100644 index 0000000..bab41a6 --- /dev/null +++ b/src/tests/filesys/extended/dir-rm-tree.c @@ -0,0 +1,62 @@ +/* Creates directories /0/0/0 through /3/2/2 and files in the + leaf directories, then removes them. */ + +#include <stdarg.h> +#include <stdio.h> +#include <syscall.h> +#include "tests/filesys/extended/mk-tree.h" +#include "tests/lib.h" +#include "tests/main.h" + +static void remove_tree (int at, int bt, int ct, int dt); + +void +test_main (void) +{ + make_tree (4, 3, 3, 4); + remove_tree (4, 3, 3, 4); +} + +static void do_remove (const char *format, ...) PRINTF_FORMAT (1, 2); + +static void +remove_tree (int at, int bt, int ct, int dt) +{ + char try[128]; + int a, b, c, d; + + msg ("removing /0/0/0/0 through /%d/%d/%d/%d...", + at - 1, bt - 1, ct - 1, dt - 1); + quiet = true; + for (a = 0; a < at; a++) + { + for (b = 0; b < bt; b++) + { + for (c = 0; c < ct; c++) + { + for (d = 0; d < dt; d++) + do_remove ("/%d/%d/%d/%d", a, b, c, d); + do_remove ("/%d/%d/%d", a, b, c); + } + do_remove ("/%d/%d", a, b); + } + do_remove ("/%d", a); + } + quiet = false; + + snprintf (try, sizeof (try), "/%d/%d/%d/%d", at - 1, 0, ct - 1, 0); + CHECK (open (try) == -1, "open \"%s\" (must return -1)", try); +} + +static void +do_remove (const char *format, ...) +{ + char name[128]; + va_list args; + + va_start (args, format); + vsnprintf (name, sizeof name, format, args); + va_end (args); + + CHECK (remove (name), "remove \"%s\"", name); +} diff --git a/src/tests/filesys/extended/dir-rm-tree.ck b/src/tests/filesys/extended/dir-rm-tree.ck new file mode 100644 index 0000000..587b493 --- /dev/null +++ b/src/tests/filesys/extended/dir-rm-tree.ck @@ -0,0 +1,14 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); +(dir-rm-tree) begin +(dir-rm-tree) creating /0/0/0/0 through /3/2/2/3... +(dir-rm-tree) open "/0/2/0/3" +(dir-rm-tree) close "/0/2/0/3" +(dir-rm-tree) removing /0/0/0/0 through /3/2/2/3... +(dir-rm-tree) open "/3/0/2/0" (must return -1) +(dir-rm-tree) end +EOF +pass; diff --git a/src/tests/filesys/extended/dir-rmdir-persistence.ck b/src/tests/filesys/extended/dir-rmdir-persistence.ck new file mode 100644 index 0000000..562c451 --- /dev/null +++ b/src/tests/filesys/extended/dir-rmdir-persistence.ck @@ -0,0 +1,6 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_archive ({}); +pass; diff --git a/src/tests/filesys/extended/dir-rmdir.c b/src/tests/filesys/extended/dir-rmdir.c new file mode 100644 index 0000000..b3cbc6f --- /dev/null +++ b/src/tests/filesys/extended/dir-rmdir.c @@ -0,0 +1,14 @@ +/* Creates and removes a directory, then makes sure that it's + really gone. */ + +#include <syscall.h> +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + CHECK (mkdir ("a"), "mkdir \"a\""); + CHECK (remove ("a"), "rmdir \"a\""); + CHECK (!chdir ("a"), "chdir \"a\" (must return false)"); +} diff --git a/src/tests/filesys/extended/dir-rmdir.ck b/src/tests/filesys/extended/dir-rmdir.ck new file mode 100644 index 0000000..e0d8922 --- /dev/null +++ b/src/tests/filesys/extended/dir-rmdir.ck @@ -0,0 +1,12 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); +(dir-rmdir) begin +(dir-rmdir) mkdir "a" +(dir-rmdir) rmdir "a" +(dir-rmdir) chdir "a" (must return false) +(dir-rmdir) end +EOF +pass; diff --git a/src/tests/filesys/extended/dir-under-file-persistence.ck b/src/tests/filesys/extended/dir-under-file-persistence.ck new file mode 100644 index 0000000..67ca528 --- /dev/null +++ b/src/tests/filesys/extended/dir-under-file-persistence.ck @@ -0,0 +1,6 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_archive ({"abc" => ['']}); +pass; diff --git a/src/tests/filesys/extended/dir-under-file.c b/src/tests/filesys/extended/dir-under-file.c new file mode 100644 index 0000000..973a8b1 --- /dev/null +++ b/src/tests/filesys/extended/dir-under-file.c @@ -0,0 +1,13 @@ +/* Tries to create a directory with the same name as an existing + file, which must return failure. */ + +#include <syscall.h> +#include "tests/lib.h" +#include "tests/main.h" + +void +test_main (void) +{ + CHECK (create ("abc", 0), "create \"abc\""); + CHECK (!mkdir ("abc"), "mkdir \"abc\" (must return false)"); +} diff --git a/src/tests/filesys/extended/dir-under-file.ck b/src/tests/filesys/extended/dir-under-file.ck new file mode 100644 index 0000000..cce23b4 --- /dev/null +++ b/src/tests/filesys/extended/dir-under-file.ck @@ -0,0 +1,11 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); +(dir-under-file) begin +(dir-under-file) create "abc" +(dir-under-file) mkdir "abc" (must return false) +(dir-under-file) end +EOF +pass; diff --git a/src/tests/filesys/extended/dir-vine-persistence.ck b/src/tests/filesys/extended/dir-vine-persistence.ck new file mode 100644 index 0000000..698ef01 --- /dev/null +++ b/src/tests/filesys/extended/dir-vine-persistence.ck @@ -0,0 +1,37 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +# The archive should look like this: +# +# 40642 dir-vine +# 42479 tar +# 0 start +# 11 start/file0 +# 0 start/dir0 +# 11 start/dir0/file1 +# 0 start/dir0/dir1 +# 11 start/dir0/dir1/file2 +# 0 start/dir0/dir1/dir2 +# 11 start/dir0/dir1/dir2/file3 +# 0 start/dir0/dir1/dir2/dir3 +# 11 start/dir0/dir1/dir2/dir3/file4 +# 0 start/dir0/dir1/dir2/dir3/dir4 +# 11 start/dir0/dir1/dir2/dir3/dir4/file5 +# 0 start/dir0/dir1/dir2/dir3/dir4/dir5 +# 11 start/dir0/dir1/dir2/dir3/dir4/dir5/file6 +# 0 start/dir0/dir1/dir2/dir3/dir4/dir5/dir6 +# 11 start/dir0/dir1/dir2/dir3/dir4/dir5/dir6/file7 +# 0 start/dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7 +# 11 start/dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/file8 +# 0 start/dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8 +# 11 start/dir0/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/file9 +# 0 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; diff --git a/src/tests/filesys/extended/dir-vine.c b/src/tests/filesys/extended/dir-vine.c new file mode 100644 index 0000000..8a31c38 --- /dev/null +++ b/src/tests/filesys/extended/dir-vine.c @@ -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 index 0000000..db452b0 --- /dev/null +++ b/src/tests/filesys/extended/dir-vine.ck @@ -0,0 +1,11 @@ +# -*- 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 +pass; diff --git a/src/tests/filesys/extended/grow-create-persistence.ck b/src/tests/filesys/extended/grow-create-persistence.ck new file mode 100644 index 0000000..bbcb24f --- /dev/null +++ b/src/tests/filesys/extended/grow-create-persistence.ck @@ -0,0 +1,6 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_archive ({"blargle" => ['']}); +pass; diff --git a/src/tests/filesys/extended/grow-create.c b/src/tests/filesys/extended/grow-create.c new file mode 100644 index 0000000..9ccc4ea --- /dev/null +++ b/src/tests/filesys/extended/grow-create.c @@ -0,0 +1,4 @@ +/* Create a file of size 0. */ + +#define TEST_SIZE 0 +#include "tests/filesys/create.inc" diff --git a/src/tests/filesys/extended/grow-create.ck b/src/tests/filesys/extended/grow-create.ck new file mode 100644 index 0000000..b2e69d1 --- /dev/null +++ b/src/tests/filesys/extended/grow-create.ck @@ -0,0 +1,13 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); +(grow-create) begin +(grow-create) create "blargle" +(grow-create) open "blargle" for verification +(grow-create) verified contents of "blargle" +(grow-create) close "blargle" +(grow-create) end +EOF +pass; diff --git a/src/tests/filesys/extended/grow-dir-lg-persistence.ck b/src/tests/filesys/extended/grow-dir-lg-persistence.ck new file mode 100644 index 0000000..989a322 --- /dev/null +++ b/src/tests/filesys/extended/grow-dir-lg-persistence.ck @@ -0,0 +1,9 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +use tests::random; +my ($fs); +$fs->{'x'}{"file$_"} = [random_bytes (512)] foreach 0...49; +check_archive ($fs); +pass; diff --git a/src/tests/filesys/extended/grow-dir-lg.c b/src/tests/filesys/extended/grow-dir-lg.c new file mode 100644 index 0000000..20a194b --- /dev/null +++ b/src/tests/filesys/extended/grow-dir-lg.c @@ -0,0 +1,6 @@ +/* Creates a directory, + then creates 50 files in that directory. */ + +#define FILE_CNT 50 +#define DIRECTORY "/x" +#include "tests/filesys/extended/grow-dir.inc" diff --git a/src/tests/filesys/extended/grow-dir-lg.ck b/src/tests/filesys/extended/grow-dir-lg.ck new file mode 100644 index 0000000..ec58bd3 --- /dev/null +++ b/src/tests/filesys/extended/grow-dir-lg.ck @@ -0,0 +1,61 @@ +# -*- perl -*- +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 +(grow-dir-lg) creating and checking "/x/file0" +(grow-dir-lg) creating and checking "/x/file1" +(grow-dir-lg) creating and checking "/x/file2" +(grow-dir-lg) creating and checking "/x/file3" +(grow-dir-lg) creating and checking "/x/file4" +(grow-dir-lg) creating and checking "/x/file5" +(grow-dir-lg) creating and checking "/x/file6" +(grow-dir-lg) creating and checking "/x/file7" +(grow-dir-lg) creating and checking "/x/file8" +(grow-dir-lg) creating and checking "/x/file9" +(grow-dir-lg) creating and checking "/x/file10" +(grow-dir-lg) creating and checking "/x/file11" +(grow-dir-lg) creating and checking "/x/file12" +(grow-dir-lg) creating and checking "/x/file13" +(grow-dir-lg) creating and checking "/x/file14" +(grow-dir-lg) creating and checking "/x/file15" +(grow-dir-lg) creating and checking "/x/file16" +(grow-dir-lg) creating and checking "/x/file17" +(grow-dir-lg) creating and checking "/x/file18" +(grow-dir-lg) creating and checking "/x/file19" +(grow-dir-lg) creating and checking "/x/file20" +(grow-dir-lg) creating and checking "/x/file21" +(grow-dir-lg) creating and checking "/x/file22" +(grow-dir-lg) creating and checking "/x/file23" +(grow-dir-lg) creating and checking "/x/file24" +(grow-dir-lg) creating and checking "/x/file25" +(grow-dir-lg) creating and checking "/x/file26" +(grow-dir-lg) creating and checking "/x/file27" +(grow-dir-lg) creating and checking "/x/file28" +(grow-dir-lg) creating and checking "/x/file29" +(grow-dir-lg) creating and checking "/x/file30" +(grow-dir-lg) creating and checking "/x/file31" +(grow-dir-lg) creating and checking "/x/file32" +(grow-dir-lg) creating and checking "/x/file33" +(grow-dir-lg) creating and checking "/x/file34" +(grow-dir-lg) creating and checking "/x/file35" +(grow-dir-lg) creating and checking "/x/file36" +(grow-dir-lg) creating and checking "/x/file37" +(grow-dir-lg) creating and checking "/x/file38" +(grow-dir-lg) creating and checking "/x/file39" +(grow-dir-lg) creating and checking "/x/file40" +(grow-dir-lg) creating and checking "/x/file41" +(grow-dir-lg) creating and checking "/x/file42" +(grow-dir-lg) creating and checking "/x/file43" +(grow-dir-lg) creating and checking "/x/file44" +(grow-dir-lg) creating and checking "/x/file45" +(grow-dir-lg) creating and checking "/x/file46" +(grow-dir-lg) creating and checking "/x/file47" +(grow-dir-lg) creating and checking "/x/file48" +(grow-dir-lg) creating and checking "/x/file49" +(grow-dir-lg) end +EOF +pass; diff --git a/src/tests/filesys/extended/grow-dir.inc b/src/tests/filesys/extended/grow-dir.inc new file mode 100644 index 0000000..bee0ba0 --- /dev/null +++ b/src/tests/filesys/extended/grow-dir.inc @@ -0,0 +1,41 @@ +/* -*- c -*- */ + +#include <syscall.h> +#include <stdio.h> +#include "tests/filesys/seq-test.h" +#include "tests/lib.h" +#include "tests/main.h" + +static char buf[512]; + +static size_t +return_block_size (void) +{ + return sizeof buf; +} + +void +test_main (void) +{ + size_t i; + +#ifdef DIRECTORY + CHECK (mkdir (DIRECTORY), "mkdir %s", DIRECTORY); +#define DIR_PREFIX DIRECTORY "/" +#else +#define DIR_PREFIX "" +#endif + for (i = 0; i < FILE_CNT; i++) + { + char file_name[128]; + snprintf (file_name, sizeof file_name, "%sfile%zu", DIR_PREFIX, i); + + msg ("creating and checking \"%s\"", file_name); + + quiet = true; + seq_test (file_name, + buf, sizeof buf, sizeof buf, + return_block_size, NULL); + quiet = false; + } +} diff --git a/src/tests/filesys/extended/grow-file-size-persistence.ck b/src/tests/filesys/extended/grow-file-size-persistence.ck new file mode 100644 index 0000000..150f383 --- /dev/null +++ b/src/tests/filesys/extended/grow-file-size-persistence.ck @@ -0,0 +1,7 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +use tests::random; +check_archive ({"testfile" => [random_bytes (2134)]}); +pass; diff --git a/src/tests/filesys/extended/grow-file-size.c b/src/tests/filesys/extended/grow-file-size.c new file mode 100644 index 0000000..3ce8588 --- /dev/null +++ b/src/tests/filesys/extended/grow-file-size.c @@ -0,0 +1,33 @@ +/* Grows a file from 0 bytes to 2,134 bytes, 37 bytes at a time, + and checks that the file's size is reported correctly at each + step. */ + +#include <syscall.h> +#include "tests/filesys/seq-test.h" +#include "tests/lib.h" +#include "tests/main.h" + +static char buf[2134]; + +static size_t +return_block_size (void) +{ + return 37; +} + +static void +check_file_size (int fd, long ofs) +{ + long size = filesize (fd); + if (size != ofs) + fail ("filesize not updated properly: should be %ld, actually %ld", + ofs, size); +} + +void +test_main (void) +{ + seq_test ("testfile", + buf, sizeof buf, 0, + return_block_size, check_file_size); +} diff --git a/src/tests/filesys/extended/grow-file-size.ck b/src/tests/filesys/extended/grow-file-size.ck new file mode 100644 index 0000000..d81feff --- /dev/null +++ b/src/tests/filesys/extended/grow-file-size.ck @@ -0,0 +1,17 @@ +# -*- perl -*- +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" +(grow-file-size) open "testfile" +(grow-file-size) writing "testfile" +(grow-file-size) close "testfile" +(grow-file-size) open "testfile" for verification +(grow-file-size) verified contents of "testfile" +(grow-file-size) close "testfile" +(grow-file-size) end +EOF +pass; diff --git a/src/tests/filesys/extended/grow-root-lg-persistence.ck b/src/tests/filesys/extended/grow-root-lg-persistence.ck new file mode 100644 index 0000000..1692f46 --- /dev/null +++ b/src/tests/filesys/extended/grow-root-lg-persistence.ck @@ -0,0 +1,9 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +use tests::random; +my ($fs); +$fs->{"file$_"} = [random_bytes (512)] foreach 0...49; +check_archive ($fs); +pass; diff --git a/src/tests/filesys/extended/grow-root-lg.c b/src/tests/filesys/extended/grow-root-lg.c new file mode 100644 index 0000000..d8d6c09 --- /dev/null +++ b/src/tests/filesys/extended/grow-root-lg.c @@ -0,0 +1,4 @@ +/* Creates 50 files in the root directory. */ + +#define FILE_CNT 50 +#include "tests/filesys/extended/grow-dir.inc" diff --git a/src/tests/filesys/extended/grow-root-lg.ck b/src/tests/filesys/extended/grow-root-lg.ck new file mode 100644 index 0000000..b174bc9 --- /dev/null +++ b/src/tests/filesys/extended/grow-root-lg.ck @@ -0,0 +1,60 @@ +# -*- perl -*- +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" +(grow-root-lg) creating and checking "file1" +(grow-root-lg) creating and checking "file2" +(grow-root-lg) creating and checking "file3" +(grow-root-lg) creating and checking "file4" +(grow-root-lg) creating and checking "file5" +(grow-root-lg) creating and checking "file6" +(grow-root-lg) creating and checking "file7" +(grow-root-lg) creating and checking "file8" +(grow-root-lg) creating and checking "file9" +(grow-root-lg) creating and checking "file10" +(grow-root-lg) creating and checking "file11" +(grow-root-lg) creating and checking "file12" +(grow-root-lg) creating and checking "file13" +(grow-root-lg) creating and checking "file14" +(grow-root-lg) creating and checking "file15" +(grow-root-lg) creating and checking "file16" +(grow-root-lg) creating and checking "file17" +(grow-root-lg) creating and checking "file18" +(grow-root-lg) creating and checking "file19" +(grow-root-lg) creating and checking "file20" +(grow-root-lg) creating and checking "file21" +(grow-root-lg) creating and checking "file22" +(grow-root-lg) creating and checking "file23" +(grow-root-lg) creating and checking "file24" +(grow-root-lg) creating and checking "file25" +(grow-root-lg) creating and checking "file26" +(grow-root-lg) creating and checking "file27" +(grow-root-lg) creating and checking "file28" +(grow-root-lg) creating and checking "file29" +(grow-root-lg) creating and checking "file30" +(grow-root-lg) creating and checking "file31" +(grow-root-lg) creating and checking "file32" +(grow-root-lg) creating and checking "file33" +(grow-root-lg) creating and checking "file34" +(grow-root-lg) creating and checking "file35" +(grow-root-lg) creating and checking "file36" +(grow-root-lg) creating and checking "file37" +(grow-root-lg) creating and checking "file38" +(grow-root-lg) creating and checking "file39" +(grow-root-lg) creating and checking "file40" +(grow-root-lg) creating and checking "file41" +(grow-root-lg) creating and checking "file42" +(grow-root-lg) creating and checking "file43" +(grow-root-lg) creating and checking "file44" +(grow-root-lg) creating and checking "file45" +(grow-root-lg) creating and checking "file46" +(grow-root-lg) creating and checking "file47" +(grow-root-lg) creating and checking "file48" +(grow-root-lg) creating and checking "file49" +(grow-root-lg) end +EOF +pass; diff --git a/src/tests/filesys/extended/grow-root-sm-persistence.ck b/src/tests/filesys/extended/grow-root-sm-persistence.ck new file mode 100644 index 0000000..2b0b8ab --- /dev/null +++ b/src/tests/filesys/extended/grow-root-sm-persistence.ck @@ -0,0 +1,9 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +use tests::random; +my ($fs); +$fs->{"file$_"} = [random_bytes (512)] foreach 0...19; +check_archive ($fs); +pass; diff --git a/src/tests/filesys/extended/grow-root-sm.c b/src/tests/filesys/extended/grow-root-sm.c new file mode 100644 index 0000000..ee375d5 --- /dev/null +++ b/src/tests/filesys/extended/grow-root-sm.c @@ -0,0 +1,4 @@ +/* Creates 20 files in the root directory. */ + +#define FILE_CNT 20 +#include "tests/filesys/extended/grow-dir.inc" diff --git a/src/tests/filesys/extended/grow-root-sm.ck b/src/tests/filesys/extended/grow-root-sm.ck new file mode 100644 index 0000000..1aac7e9 --- /dev/null +++ b/src/tests/filesys/extended/grow-root-sm.ck @@ -0,0 +1,30 @@ +# -*- perl -*- +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" +(grow-root-sm) creating and checking "file1" +(grow-root-sm) creating and checking "file2" +(grow-root-sm) creating and checking "file3" +(grow-root-sm) creating and checking "file4" +(grow-root-sm) creating and checking "file5" +(grow-root-sm) creating and checking "file6" +(grow-root-sm) creating and checking "file7" +(grow-root-sm) creating and checking "file8" +(grow-root-sm) creating and checking "file9" +(grow-root-sm) creating and checking "file10" +(grow-root-sm) creating and checking "file11" +(grow-root-sm) creating and checking "file12" +(grow-root-sm) creating and checking "file13" +(grow-root-sm) creating and checking "file14" +(grow-root-sm) creating and checking "file15" +(grow-root-sm) creating and checking "file16" +(grow-root-sm) creating and checking "file17" +(grow-root-sm) creating and checking "file18" +(grow-root-sm) creating and checking "file19" +(grow-root-sm) end +EOF +pass; diff --git a/src/tests/filesys/extended/grow-seq-lg-persistence.ck b/src/tests/filesys/extended/grow-seq-lg-persistence.ck new file mode 100644 index 0000000..41aaae0 --- /dev/null +++ b/src/tests/filesys/extended/grow-seq-lg-persistence.ck @@ -0,0 +1,7 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +use tests::random; +check_archive ({"testme" => [random_bytes (72943)]}); +pass; diff --git a/src/tests/filesys/extended/grow-seq-lg.c b/src/tests/filesys/extended/grow-seq-lg.c new file mode 100644 index 0000000..3108d17 --- /dev/null +++ b/src/tests/filesys/extended/grow-seq-lg.c @@ -0,0 +1,5 @@ +/* Grows a file from 0 bytes to 72,943 bytes, 1,234 bytes at a + time. */ + +#define TEST_SIZE 72943 +#include "tests/filesys/extended/grow-seq.inc" diff --git a/src/tests/filesys/extended/grow-seq-lg.ck b/src/tests/filesys/extended/grow-seq-lg.ck new file mode 100644 index 0000000..90fcd8c --- /dev/null +++ b/src/tests/filesys/extended/grow-seq-lg.ck @@ -0,0 +1,17 @@ +# -*- perl -*- +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" +(grow-seq-lg) open "testme" +(grow-seq-lg) writing "testme" +(grow-seq-lg) close "testme" +(grow-seq-lg) open "testme" for verification +(grow-seq-lg) verified contents of "testme" +(grow-seq-lg) close "testme" +(grow-seq-lg) end +EOF +pass; diff --git a/src/tests/filesys/extended/grow-seq-sm-persistence.ck b/src/tests/filesys/extended/grow-seq-sm-persistence.ck new file mode 100644 index 0000000..6cb0bd8 --- /dev/null +++ b/src/tests/filesys/extended/grow-seq-sm-persistence.ck @@ -0,0 +1,7 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +use tests::random; +check_archive ({"testme" => [random_bytes (5678)]}); +pass; diff --git a/src/tests/filesys/extended/grow-seq-sm.c b/src/tests/filesys/extended/grow-seq-sm.c new file mode 100644 index 0000000..3656e2e --- /dev/null +++ b/src/tests/filesys/extended/grow-seq-sm.c @@ -0,0 +1,5 @@ +/* Grows a file from 0 bytes to 5,678 bytes, 1,234 bytes at a + time. */ + +#define TEST_SIZE 5678 +#include "tests/filesys/extended/grow-seq.inc" diff --git a/src/tests/filesys/extended/grow-seq-sm.ck b/src/tests/filesys/extended/grow-seq-sm.ck new file mode 100644 index 0000000..5cf4518 --- /dev/null +++ b/src/tests/filesys/extended/grow-seq-sm.ck @@ -0,0 +1,17 @@ +# -*- perl -*- +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" +(grow-seq-sm) open "testme" +(grow-seq-sm) writing "testme" +(grow-seq-sm) close "testme" +(grow-seq-sm) open "testme" for verification +(grow-seq-sm) verified contents of "testme" +(grow-seq-sm) close "testme" +(grow-seq-sm) end +EOF +pass; diff --git a/src/tests/filesys/extended/grow-seq.inc b/src/tests/filesys/extended/grow-seq.inc new file mode 100644 index 0000000..1b7710c --- /dev/null +++ b/src/tests/filesys/extended/grow-seq.inc @@ -0,0 +1,20 @@ +/* -*- c -*- */ + +#include "tests/filesys/seq-test.h" +#include "tests/main.h" + +static char buf[TEST_SIZE]; + +static size_t +return_block_size (void) +{ + return 1234; +} + +void +test_main (void) +{ + seq_test ("testme", + buf, sizeof buf, 0, + return_block_size, NULL); +} diff --git a/src/tests/filesys/extended/grow-sparse-persistence.ck b/src/tests/filesys/extended/grow-sparse-persistence.ck new file mode 100644 index 0000000..3f06a5b --- /dev/null +++ b/src/tests/filesys/extended/grow-sparse-persistence.ck @@ -0,0 +1,6 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_archive ({"testfile" => ["\0" x 76543]}); +pass; diff --git a/src/tests/filesys/extended/grow-sparse.c b/src/tests/filesys/extended/grow-sparse.c new file mode 100644 index 0000000..6eab210 --- /dev/null +++ b/src/tests/filesys/extended/grow-sparse.c @@ -0,0 +1,25 @@ +/* Tests that seeking past the end of a file and writing will + properly zero out the region in between. */ + +#include <syscall.h> +#include "tests/lib.h" +#include "tests/main.h" + +static char buf[76543]; + +void +test_main (void) +{ + const char *file_name = "testfile"; + 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, sizeof buf - 1); + CHECK (write (fd, &zero, 1) > 0, "write \"%s\"", file_name); + msg ("close \"%s\"", file_name); + close (fd); + check_file (file_name, buf, sizeof buf); +} diff --git a/src/tests/filesys/extended/grow-sparse.ck b/src/tests/filesys/extended/grow-sparse.ck new file mode 100644 index 0000000..379ba2c --- /dev/null +++ b/src/tests/filesys/extended/grow-sparse.ck @@ -0,0 +1,17 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); +(grow-sparse) begin +(grow-sparse) create "testfile" +(grow-sparse) open "testfile" +(grow-sparse) seek "testfile" +(grow-sparse) write "testfile" +(grow-sparse) close "testfile" +(grow-sparse) open "testfile" for verification +(grow-sparse) verified contents of "testfile" +(grow-sparse) close "testfile" +(grow-sparse) end +EOF +pass; diff --git a/src/tests/filesys/extended/grow-tell-persistence.ck b/src/tests/filesys/extended/grow-tell-persistence.ck new file mode 100644 index 0000000..d93a422 --- /dev/null +++ b/src/tests/filesys/extended/grow-tell-persistence.ck @@ -0,0 +1,7 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +use tests::random; +check_archive ({"foobar" => [random_bytes (2134)]}); +pass; diff --git a/src/tests/filesys/extended/grow-tell.c b/src/tests/filesys/extended/grow-tell.c new file mode 100644 index 0000000..5f5da5b --- /dev/null +++ b/src/tests/filesys/extended/grow-tell.c @@ -0,0 +1,32 @@ +/* Checks that growing a file updates the file position + correctly. */ + +#include <syscall.h> +#include "tests/filesys/seq-test.h" +#include "tests/lib.h" +#include "tests/main.h" + +static char buf[2134]; + +static size_t +return_block_size (void) +{ + return 37; +} + +static void +check_tell (int fd, long ofs) +{ + long pos = tell (fd); + if (pos != ofs) + fail ("file position not updated properly: should be %ld, actually %ld", + ofs, pos); +} + +void +test_main (void) +{ + seq_test ("foobar", + buf, sizeof buf, 0, + return_block_size, check_tell); +} diff --git a/src/tests/filesys/extended/grow-tell.ck b/src/tests/filesys/extended/grow-tell.ck new file mode 100644 index 0000000..fe94707 --- /dev/null +++ b/src/tests/filesys/extended/grow-tell.ck @@ -0,0 +1,17 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +use tests::random; +check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); +(grow-tell) begin +(grow-tell) create "foobar" +(grow-tell) open "foobar" +(grow-tell) writing "foobar" +(grow-tell) close "foobar" +(grow-tell) open "foobar" for verification +(grow-tell) verified contents of "foobar" +(grow-tell) close "foobar" +(grow-tell) end +EOF +pass; diff --git a/src/tests/filesys/extended/grow-two-files-persistence.ck b/src/tests/filesys/extended/grow-two-files-persistence.ck new file mode 100644 index 0000000..1c4ced1 --- /dev/null +++ b/src/tests/filesys/extended/grow-two-files-persistence.ck @@ -0,0 +1,9 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +use tests::random; +my ($a) = random_bytes (8143); +my ($b) = random_bytes (8143); +check_archive ({"a" => [$a], "b" => [$b]}); +pass; diff --git a/src/tests/filesys/extended/grow-two-files.c b/src/tests/filesys/extended/grow-two-files.c new file mode 100644 index 0000000..6a8fb1c --- /dev/null +++ b/src/tests/filesys/extended/grow-two-files.c @@ -0,0 +1,62 @@ +/* Grows two files in parallel and checks that their contents are + correct. */ + +#include <random.h> +#include <syscall.h> +#include "tests/lib.h" +#include "tests/main.h" + +#define FILE_SIZE 8143 +static char buf_a[FILE_SIZE]; +static char buf_b[FILE_SIZE]; + +static void +write_some_bytes (const char *file_name, int fd, const char *buf, size_t *ofs) +{ + if (*ofs < FILE_SIZE) + { + size_t block_size = random_ulong () % (FILE_SIZE / 8) + 1; + size_t ret_val; + if (block_size > FILE_SIZE - *ofs) + block_size = FILE_SIZE - *ofs; + + ret_val = write (fd, buf + *ofs, block_size); + if (ret_val != block_size) + fail ("write %zu bytes at offset %zu in \"%s\" returned %zu", + block_size, *ofs, file_name, ret_val); + *ofs += block_size; + } +} + +void +test_main (void) +{ + int fd_a, fd_b; + size_t ofs_a = 0, ofs_b = 0; + + random_init (0); + random_bytes (buf_a, sizeof buf_a); + random_bytes (buf_b, sizeof buf_b); + + CHECK (create ("a", 0), "create \"a\""); + CHECK (create ("b", 0), "create \"b\""); + + CHECK ((fd_a = open ("a")) > 1, "open \"a\""); + CHECK ((fd_b = open ("b")) > 1, "open \"b\""); + + msg ("write \"a\" and \"b\" alternately"); + while (ofs_a < FILE_SIZE || ofs_b < FILE_SIZE) + { + write_some_bytes ("a", fd_a, buf_a, &ofs_a); + write_some_bytes ("b", fd_b, buf_b, &ofs_b); + } + + msg ("close \"a\""); + close (fd_a); + + msg ("close \"b\""); + close (fd_b); + + check_file ("a", buf_a, FILE_SIZE); + check_file ("b", buf_b, FILE_SIZE); +} diff --git a/src/tests/filesys/extended/grow-two-files.ck b/src/tests/filesys/extended/grow-two-files.ck new file mode 100644 index 0000000..b5e754a --- /dev/null +++ b/src/tests/filesys/extended/grow-two-files.ck @@ -0,0 +1,23 @@ +# -*- perl -*- +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" +(grow-two-files) create "b" +(grow-two-files) open "a" +(grow-two-files) open "b" +(grow-two-files) write "a" and "b" alternately +(grow-two-files) close "a" +(grow-two-files) close "b" +(grow-two-files) open "a" for verification +(grow-two-files) verified contents of "a" +(grow-two-files) close "a" +(grow-two-files) open "b" for verification +(grow-two-files) verified contents of "b" +(grow-two-files) close "b" +(grow-two-files) end +EOF +pass; diff --git a/src/tests/filesys/extended/mk-tree.c b/src/tests/filesys/extended/mk-tree.c new file mode 100644 index 0000000..a36bb88 --- /dev/null +++ b/src/tests/filesys/extended/mk-tree.c @@ -0,0 +1,67 @@ +/* Library function for creating a tree of directories. */ + +#include <stdio.h> +#include <syscall.h> +#include "tests/filesys/extended/mk-tree.h" +#include "tests/lib.h" + +static void do_mkdir (const char *format, ...) PRINTF_FORMAT (1, 2); +static void do_touch (const char *format, ...) PRINTF_FORMAT (1, 2); + +void +make_tree (int at, int bt, int ct, int dt) +{ + char try[128]; + int a, b, c, d; + int fd; + + msg ("creating /0/0/0/0 through /%d/%d/%d/%d...", + at - 1, bt - 1, ct - 1, dt - 1); + quiet = true; + for (a = 0; a < at; a++) + { + do_mkdir ("/%d", a); + for (b = 0; b < bt; b++) + { + do_mkdir ("/%d/%d", a, b); + for (c = 0; c < ct; c++) + { + do_mkdir ("/%d/%d/%d", a, b, c); + for (d = 0; d < dt; d++) + do_touch ("/%d/%d/%d/%d", a, b, c, d); + } + } + } + quiet = false; + + snprintf (try, sizeof try, "/%d/%d/%d/%d", 0, bt - 1, 0, dt - 1); + CHECK ((fd = open (try)) > 1, "open \"%s\"", try); + msg ("close \"%s\"", try); + close (fd); +} + +static void +do_mkdir (const char *format, ...) +{ + char dir[128]; + va_list args; + + va_start (args, format); + vsnprintf (dir, sizeof dir, format, args); + va_end (args); + + CHECK (mkdir (dir), "mkdir \"%s\"", dir); +} + +static void +do_touch (const char *format, ...) +{ + char file[128]; + va_list args; + + va_start (args, format); + vsnprintf (file, sizeof file, format, args); + va_end (args); + + CHECK (create (file, 0), "create \"%s\"", file); +} diff --git a/src/tests/filesys/extended/mk-tree.h b/src/tests/filesys/extended/mk-tree.h new file mode 100644 index 0000000..df0d5a6 --- /dev/null +++ b/src/tests/filesys/extended/mk-tree.h @@ -0,0 +1,6 @@ +#ifndef TESTS_FILESYS_EXTENDED_MK_TREE_H +#define TESTS_FILESYS_EXTENDED_MK_TREE_H + +void make_tree (int at, int bt, int ct, int dt); + +#endif /* tests/filesys/extended/mk-tree.h */ diff --git a/src/tests/filesys/extended/syn-rw-persistence.ck b/src/tests/filesys/extended/syn-rw-persistence.ck new file mode 100644 index 0000000..62d57ee --- /dev/null +++ b/src/tests/filesys/extended/syn-rw-persistence.ck @@ -0,0 +1,8 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +use tests::random; +check_archive ({"child-syn-rw" => "tests/filesys/extended/child-syn-rw", + "logfile" => [random_bytes (8 * 512)]}); +pass; diff --git a/src/tests/filesys/extended/syn-rw.c b/src/tests/filesys/extended/syn-rw.c new file mode 100644 index 0000000..657dfb5 --- /dev/null +++ b/src/tests/filesys/extended/syn-rw.c @@ -0,0 +1,35 @@ +/* Grows a file in chunks while subprocesses read the growing + file. */ + +#include <random.h> +#include <syscall.h> +#include "tests/filesys/extended/syn-rw.h" +#include "tests/lib.h" +#include "tests/main.h" + +char buf[BUF_SIZE]; + +#define CHILD_CNT 4 + +void +test_main (void) +{ + pid_t children[CHILD_CNT]; + size_t ofs; + int fd; + + CHECK (create (file_name, 0), "create \"%s\"", file_name); + CHECK ((fd = open (file_name)) > 1, "open \"%s\"", file_name); + + exec_children ("child-syn-rw", children, CHILD_CNT); + + random_bytes (buf, sizeof buf); + quiet = true; + for (ofs = 0; ofs < BUF_SIZE; ofs += CHUNK_SIZE) + CHECK (write (fd, buf + ofs, CHUNK_SIZE) > 0, + "write %d bytes at offset %zu in \"%s\"", + (int) CHUNK_SIZE, ofs, file_name); + quiet = false; + + wait_children (children, CHILD_CNT); +} diff --git a/src/tests/filesys/extended/syn-rw.ck b/src/tests/filesys/extended/syn-rw.ck new file mode 100644 index 0000000..ac82aa8 --- /dev/null +++ b/src/tests/filesys/extended/syn-rw.ck @@ -0,0 +1,20 @@ +# -*- perl -*- +use strict; +use warnings; +use tests::tests; +use tests::random; +check_expected (IGNORE_EXIT_CODES => 1, [<<'EOF']); +(syn-rw) begin +(syn-rw) create "logfile" +(syn-rw) open "logfile" +(syn-rw) exec child 1 of 4: "child-syn-rw 0" +(syn-rw) exec child 2 of 4: "child-syn-rw 1" +(syn-rw) exec child 3 of 4: "child-syn-rw 2" +(syn-rw) exec child 4 of 4: "child-syn-rw 3" +(syn-rw) wait for child 1 of 4 returned 0 (expected 0) +(syn-rw) wait for child 2 of 4 returned 1 (expected 1) +(syn-rw) wait for child 3 of 4 returned 2 (expected 2) +(syn-rw) wait for child 4 of 4 returned 3 (expected 3) +(syn-rw) end +EOF +pass; diff --git a/src/tests/filesys/extended/syn-rw.h b/src/tests/filesys/extended/syn-rw.h new file mode 100644 index 0000000..170aeb4 --- /dev/null +++ b/src/tests/filesys/extended/syn-rw.h @@ -0,0 +1,9 @@ +#ifndef TESTS_FILESYS_EXTENDED_SYN_RW_H +#define TESTS_FILESYS_EXTENDED_SYN_RW_H + +#define CHUNK_SIZE 8 +#define CHUNK_CNT 512 +#define BUF_SIZE (CHUNK_SIZE * CHUNK_CNT) +static const char file_name[] = "logfile"; + +#endif /* tests/filesys/extended/syn-rw.h */ diff --git a/src/tests/filesys/extended/tar.c b/src/tests/filesys/extended/tar.c new file mode 100644 index 0000000..6f70d97 --- /dev/null +++ b/src/tests/filesys/extended/tar.c @@ -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); +} + +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 = true; + 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; + } +} diff --git a/src/tests/filesys/seq-test.c b/src/tests/filesys/seq-test.c new file mode 100644 index 0000000..8ce222c --- /dev/null +++ b/src/tests/filesys/seq-test.c @@ -0,0 +1,37 @@ +#include "tests/filesys/seq-test.h" +#include <random.h> +#include <syscall.h> +#include "tests/lib.h" + +void +seq_test (const char *file_name, void *buf, size_t size, size_t initial_size, + size_t (*block_size_func) (void), + void (*check_func) (int fd, long ofs)) +{ + size_t ofs; + int fd; + + random_bytes (buf, size); + CHECK (create (file_name, initial_size), "create \"%s\"", file_name); + CHECK ((fd = open (file_name)) > 1, "open \"%s\"", file_name); + + ofs = 0; + msg ("writing \"%s\"", file_name); + while (ofs < size) + { + size_t block_size = block_size_func (); + if (block_size > size - ofs) + block_size = size - ofs; + + if (write (fd, buf + ofs, block_size) != (int) block_size) + fail ("write %zu bytes at offset %zu in \"%s\" failed", + block_size, ofs, file_name); + + ofs += block_size; + if (check_func != NULL) + check_func (fd, ofs); + } + msg ("close \"%s\"", file_name); + close (fd); + check_file (file_name, buf, size); +} diff --git a/src/tests/filesys/seq-test.h b/src/tests/filesys/seq-test.h new file mode 100644 index 0000000..0697381 --- /dev/null +++ b/src/tests/filesys/seq-test.h @@ -0,0 +1,11 @@ +#ifndef TESTS_FILESYS_SEQ_TEST_H +#define TESTS_FILESYS_SEQ_TEST_H + +#include <stddef.h> + +void seq_test (const char *file_name, + void *buf, size_t size, size_t initial_size, + size_t (*block_size_func) (void), + void (*check_func) (int fd, long ofs)); + +#endif /* tests/filesys/seq-test.h */ |
