diff --git a/bin/utest/getcwd.c b/bin/utest/getcwd.c index 68b11b74f..90be4099a 100644 --- a/bin/utest/getcwd.c +++ b/bin/utest/getcwd.c @@ -6,6 +6,8 @@ #include TEST_ADD(getcwd, 0) { + xchdir("/"); + { /* Working directory is set to root if not changed */ char buffer[256]; diff --git a/bin/utest/main.c b/bin/utest/main.c index 5ec5f46c6..a25859804 100644 --- a/bin/utest/main.c +++ b/bin/utest/main.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -102,6 +103,14 @@ static int running(void) { return pending; } +#define TMPDIR "/tmp" + +char testdir[128] = TMPDIR; + +static void testdir_cleanup(void) { + xrmdir(testdir); +} + static void run_test(sigset_t *mask, test_entry_t *te) { timeval_t tv = timestamp(); const char *name = te->name; @@ -116,6 +125,14 @@ static void run_test(sigset_t *mask, test_entry_t *te) { setpgid(0, 0); xsigprocmask(SIG_SETMASK, mask, NULL); + if (te->flags & TF_TMPDIR) { + snprintf(testdir, sizeof(testdir), TMPDIR "/%s.%d", te->name, getpid()); + xmkdir(testdir, 0); + atexit(testdir_cleanup); + } + + xchdir(testdir); + if (te->flags & TF_DEBUG) __verbose = 1; diff --git a/bin/utest/utest.h b/bin/utest/utest.h index 7ef9e7818..614cf62b2 100644 --- a/bin/utest/utest.h +++ b/bin/utest/utest.h @@ -14,6 +14,7 @@ typedef int (*test_func_t)(void); typedef enum test_flags { TF_DISABLED = INT32_MIN, /* test will return success without being executed */ TF_DEBUG = 1, /* display debug messages to stderr */ + TF_TMPDIR = 2, /* create temp di rand run the test there */ } test_flags_t; typedef struct test_entry { @@ -90,6 +91,12 @@ pid_t wait_child_terminated(pid_t pid, int signo); void wait_child_stopped(pid_t pid); void wait_child_continued(pid_t pid); +/* + * VFS test related definitions + */ + +extern char testdir[]; + /* * libc function wrappers that call die(...) on error */ @@ -134,6 +141,7 @@ void wait_child_continued(pid_t pid); #define xopen(...) NOFAIL(open, int, __VA_ARGS__) #define xpipe(...) NOFAIL_NR(pipe, __VA_ARGS__) #define xread(...) NOFAIL(read, ssize_t, __VA_ARGS__) +#define xreadlink(...) NOFAIL(readlink, ssize_t, __VA_ARGS__) #define xrmdir(...) NOFAIL_NR(rmdir, __VA_ARGS__) #define xsetgroups(...) NOFAIL_NR(setgroups, __VA_ARGS__) #define xsetresuid(...) NOFAIL_NR(setresuid, __VA_ARGS__) diff --git a/bin/utest/vfs.c b/bin/utest/vfs.c index 2aae1be94..045885d10 100644 --- a/bin/utest/vfs.c +++ b/bin/utest/vfs.c @@ -13,9 +13,6 @@ #undef FD_OFFSET #define FD_OFFSET 3 -#define TESTDIR "/tmp" -#define TESTPATH(x) TESTDIR "/" x - /* Generate pseudo random data */ static void fill_random(uint32_t *data, size_t n) { uint32_t a = 1; @@ -27,7 +24,7 @@ static void fill_random(uint32_t *data, size_t n) { } } -TEST_ADD(vfs_rw, 0) { +TEST_ADD(vfs_rw, TF_TMPDIR) { int n; void *wrbuf = malloc(16384); @@ -35,23 +32,23 @@ TEST_ADD(vfs_rw, 0) { fill_random(wrbuf, 16384); - assert_open_ok(0, TESTPATH("file"), 0, O_RDWR | O_CREAT); + assert_open_ok(0, "file", 0, O_RDWR | O_CREAT); /* Write and read aligned amount of bytes */ assert_write_ok(0, wrbuf, 4096); assert_lseek_ok(0, 0, SEEK_SET); - assert(read(3, rdbuf, 5000) == 4096); + assert(xread(3, rdbuf, 5000) == 4096); assert(!memcmp(wrbuf, rdbuf, 4096)); - assert(read(3, rdbuf, 5000) == 0); + assert(xread(3, rdbuf, 5000) == 0); assert_lseek_ok(0, 0, SEEK_SET); /* Write 12000 bytes in two batches and then partially read */ assert_write_ok(0, wrbuf, 8000); assert_write_ok(0, wrbuf + 8000, 4000); assert_lseek_ok(0, 0, SEEK_SET); - assert(read(3, rdbuf, 6000) == 6000); + assert(xread(3, rdbuf, 6000) == 6000); assert(!memcmp(wrbuf, rdbuf, 6000)); - assert(read(3, rdbuf + 6000, 12000) == 6000); + assert(xread(3, rdbuf + 6000, 12000) == 6000); assert(!memcmp(wrbuf, rdbuf, 6000)); assert_lseek_ok(0, 0, SEEK_SET); @@ -60,7 +57,7 @@ TEST_ADD(vfs_rw, 0) { assert_write_ok(0, wrbuf, 16384); assert_lseek_ok(0, 0, SEEK_SET); for (int i = 0; i < 2; i++) { - assert(read(3, rdbuf, 16384) == 16384); + assert(xread(3, rdbuf, 16384) == 16384); assert(!memcmp(wrbuf, rdbuf, 16384)); } @@ -68,80 +65,80 @@ TEST_ADD(vfs_rw, 0) { free(rdbuf); xclose(3); - xunlink(TESTPATH("file")); + xunlink("file"); return 0; } -TEST_ADD(vfs_trunc, 0) { +TEST_ADD(vfs_trunc, TF_TMPDIR) { int n; void *wrbuf = malloc(4096); void *rdbuf = malloc(8196); fill_random(wrbuf, 4096); - assert_open_ok(0, TESTPATH("file"), S_IWUSR | S_IRUSR, O_RDWR | O_CREAT); + assert_open_ok(0, "file", S_IWUSR | S_IRUSR, O_RDWR | O_CREAT); assert_write_ok(0, wrbuf, 4096); ftruncate(3, 2048); /* The file offset is bigger than size, so read should return 0 bytes. */ - assert(read(3, rdbuf, 6000) == 0); + assert(xread(3, rdbuf, 6000) == 0); assert_lseek_ok(0, 0, SEEK_SET); - assert(read(3, rdbuf, 6000) == 2048); + assert(xread(3, rdbuf, 6000) == 2048); assert(!memcmp(wrbuf, rdbuf, 2048)); ftruncate(3, 7777); assert_lseek_ok(0, 0, SEEK_SET); - assert(read(3, rdbuf, 10000) == 7777); + assert(xread(3, rdbuf, 10000) == 7777); assert(!memcmp(wrbuf, rdbuf, 2048)); /* Rest of the file should be zeroed. */ for (int i = 2048; i < 7777; i++) assert(((uint8_t *)rdbuf)[i] == 0); - truncate(TESTPATH("file"), 0); + truncate("file", 0); assert_lseek_ok(0, 0, SEEK_SET); - assert(read(3, rdbuf, 2048) == 0); + assert(xread(3, rdbuf, 2048) == 0); free(wrbuf); free(rdbuf); - unlink(TESTPATH("file")); + unlink("file"); - syscall_fail(truncate(TESTDIR, 1023), EISDIR); + syscall_fail(truncate(testdir, 1023), EISDIR); return 0; } -TEST_ADD(vfs_dir, 0) { +TEST_ADD(vfs_dir, TF_TMPDIR) { syscall_fail(mkdir("/", 0), EEXIST); - xmkdir(TESTPATH("test"), 0); - syscall_fail(mkdir(TESTPATH("test"), 0), EEXIST); - syscall_fail(mkdir(TESTPATH("/test///"), 0), EEXIST); - xrmdir(TESTPATH("test")); - xmkdir(TESTPATH("test"), 0); - - xmkdir(TESTPATH("/test2///"), 0); - xaccess(TESTPATH("test2"), 0); - - xmkdir(TESTPATH("test3"), 0); - xmkdir(TESTPATH("test3/subdir1"), 0); - xmkdir(TESTPATH("test3/subdir2"), 0); - xmkdir(TESTPATH("test3/subdir3"), 0); - syscall_fail(mkdir(TESTPATH("test3/subdir1"), 0), EEXIST); - xaccess(TESTPATH("test3/subdir2"), 0); - - syscall_fail(mkdir(TESTPATH("test4/subdir4"), 0), ENOENT); - - xrmdir(TESTPATH("test/")); - xrmdir(TESTPATH("test2")); - syscall_fail(rmdir(TESTPATH("test3")), ENOTEMPTY); - xrmdir(TESTPATH("test3/subdir1")); - xrmdir(TESTPATH("test3/subdir2")); - xrmdir(TESTPATH("test3/subdir3")); - xrmdir(TESTPATH("test3")); - syscall_fail(rmdir(TESTPATH("test3")), ENOENT); - syscall_fail(rmdir(TESTPATH("test4/subdir4")), ENOENT); - - syscall_fail(mkdir(TESTPATH("test3/subdir1"), 0), ENOENT); + xmkdir("test", 0); + syscall_fail(mkdir("test", 0), EEXIST); + syscall_fail(mkdir("./test///", 0), EEXIST); + xrmdir("test"); + xmkdir("test", 0); + + xmkdir("./test2///", 0); + xaccess("test2", 0); + + xmkdir("test3", 0); + xmkdir("test3/subdir1", 0); + xmkdir("test3/subdir2", 0); + xmkdir("test3/subdir3", 0); + syscall_fail(mkdir("test3/subdir1", 0), EEXIST); + xaccess("test3/subdir2", 0); + + syscall_fail(mkdir("test4/subdir4", 0), ENOENT); + + xrmdir("test/"); + xrmdir("test2"); + syscall_fail(rmdir("test3"), ENOTEMPTY); + xrmdir("test3/subdir1"); + xrmdir("test3/subdir2"); + xrmdir("test3/subdir3"); + xrmdir("test3"); + syscall_fail(rmdir("test3"), ENOENT); + syscall_fail(rmdir("test4/subdir4"), ENOENT); + + syscall_fail(mkdir("test3/subdir1", 0), ENOENT); syscall_fail(mkdir("/", 0), EEXIST); syscall_fail(rmdir("/tmp"), EBUSY); @@ -149,8 +146,7 @@ TEST_ADD(vfs_dir, 0) { return 0; } -TEST_ADD(vfs_relative_dir, 0) { - xchdir(TESTDIR); +TEST_ADD(vfs_relative_dir, TF_TMPDIR) { xmkdir("test", 0); syscall_fail(mkdir("test", 0), EEXIST); syscall_fail(mkdir("test///", 0), EEXIST); @@ -166,20 +162,17 @@ TEST_ADD(vfs_relative_dir, 0) { syscall_fail(mkdir("test3/subdir1", 0), EEXIST); xaccess("test3/subdir2", 0); - xrmdir(TESTPATH("test/test3/subdir1")); - xrmdir(TESTPATH("test/test3/subdir2")); - xrmdir(TESTPATH("test/test3/subdir3")); - xrmdir("test3"); - - xchdir(TESTDIR); + xchdir(".."); + xrmdir("test/test3/subdir1"); + xrmdir("test/test3/subdir2"); + xrmdir("test/test3/subdir3"); + xrmdir("test/test3"); xrmdir("test"); - xchdir("/"); + return 0; } -TEST_ADD(vfs_dot_dot_dir, 0) { - xchdir(TESTDIR); - +TEST_ADD(vfs_dot_dot_dir, TF_TMPDIR) { xmkdir("test", 0); xchdir("test"); xmkdir("test2///", 0); @@ -202,9 +195,9 @@ TEST_ADD(vfs_dot_dot_dir, 0) { } TEST_ADD(vfs_dot_dir, 0) { - syscall_fail(mkdir(TESTPATH("test/."), 0), ENOENT); + syscall_fail(mkdir("test/.", 0), ENOENT); syscall_fail(mkdir("/.", 0), EEXIST); - syscall_fail(mkdir(TESTPATH("."), 0), EEXIST); + syscall_fail(mkdir(".", 0), EEXIST); return 0; } @@ -222,84 +215,84 @@ TEST_ADD(vfs_dot_dot_across_fs, 0) { return 0; } -TEST_ADD(vfs_symlink_basic, 0) { - xsymlink("Hello, world!", TESTPATH("testlink")); +TEST_ADD(vfs_symlink_basic, TF_TMPDIR) { + xsymlink("Hello, world!", "testlink"); char buf[32]; memset(buf, 0, sizeof(buf)); - assert(readlink(TESTPATH("testlink"), buf, 1024) == 13); + assert(xreadlink("testlink", buf, 1024) == 13); string_eq("Hello, world!", buf); memset(buf, 0, sizeof(buf)); - assert(readlink(TESTPATH("testlink"), buf, 5) == 5); + assert(xreadlink("testlink", buf, 5) == 5); string_eq("Hello", buf); - syscall_fail(symlink("Hello, world!", TESTPATH("testlink")), EEXIST); + syscall_fail(symlink("Hello, world!", "testlink"), EEXIST); - xunlink(TESTPATH("testlink")); + xunlink("testlink"); return 0; } -TEST_ADD(vfs_symlink_vnr, 0) { +TEST_ADD(vfs_symlink_vnr, TF_TMPDIR) { int n; struct stat sb; ino_t fileino; - assert_open_ok(0, TESTPATH("file"), 0, O_RDWR | O_CREAT); - xstat(TESTPATH("file"), &sb); + assert_open_ok(0, "file", 0, O_RDWR | O_CREAT); + xstat("file", &sb); fileino = sb.st_ino; /* Absolute symlink */ - xsymlink(TESTPATH("file"), TESTPATH("alink")); - xstat(TESTPATH("alink"), &sb); + xsymlink("file", "alink"); + xstat("alink", &sb); assert(fileino == sb.st_ino); - xsymlink(TESTPATH("alink"), TESTPATH("alink2")); - xstat(TESTPATH("alink2"), &sb); + xsymlink("alink", "alink2"); + xstat("alink2", &sb); assert(fileino == sb.st_ino); /* Relative symlink */ - xsymlink("file", TESTPATH("rlink")); - xstat(TESTPATH("rlink"), &sb); + xsymlink("file", "rlink"); + xstat("rlink", &sb); assert(fileino == sb.st_ino); - xsymlink("alink2", TESTPATH("rlink2")); - xstat(TESTPATH("rlink2"), &sb); + xsymlink("alink2", "rlink2"); + xstat("rlink2", &sb); assert(fileino == sb.st_ino); /* Do not follow symlink */ - xlstat(TESTPATH("alink2"), &sb); + xlstat("alink2", &sb); assert(fileino != sb.st_ino); - xunlink(TESTPATH("alink")); - xunlink(TESTPATH("alink2")); - xunlink(TESTPATH("rlink")); - xunlink(TESTPATH("rlink2")); + xunlink("alink"); + xunlink("alink2"); + xunlink("rlink"); + xunlink("rlink2"); /* Symlink to directory */ - xsymlink("/tmp", TESTPATH("dlink")); - xstat(TESTPATH("dlink/file"), &sb); + xsymlink(testdir, "dlink"); + xstat("dlink/file", &sb); assert(fileino == sb.st_ino); - xunlink(TESTPATH("dlink")); + xunlink("dlink"); /* Looped symlink */ - xsymlink(TESTPATH("slink"), TESTPATH("slink")); - syscall_fail(stat(TESTPATH("slink"), &sb), ELOOP); - xunlink(TESTPATH("slink")); + xsymlink("slink", "slink"); + syscall_fail(stat("slink", &sb), ELOOP); + xunlink("slink"); /* Bad symlink */ - xsymlink(TESTPATH("nofile"), TESTPATH("blink")); - syscall_fail(stat(TESTPATH("blink"), &sb), ENOENT); - xunlink(TESTPATH("blink")); + xsymlink("nofile", "blink"); + syscall_fail(stat("blink", &sb), ENOENT); + xunlink("blink"); - xunlink(TESTPATH("file")); + xunlink("file"); return 0; } -TEST_ADD(vfs_link, 0) { +TEST_ADD(vfs_link, TF_TMPDIR) { int n; struct stat sb; ino_t fileino; @@ -309,8 +302,8 @@ TEST_ADD(vfs_link, 0) { fill_random(wrbuf, 64); /* Create file and fill it with random data */ - assert_open_ok(0, TESTPATH("file"), S_IWUSR | S_IRUSR, O_RDWR | O_CREAT); - xstat(TESTPATH("file"), &sb); + assert_open_ok(0, "file", S_IWUSR | S_IRUSR, O_RDWR | O_CREAT); + xstat("file", &sb); assert(sb.st_nlink == 1); fileino = sb.st_ino; @@ -318,79 +311,79 @@ TEST_ADD(vfs_link, 0) { assert_write_ok(0, wrbuf, 32); /* Make a hard link */ - xlink(TESTPATH("file"), TESTPATH("file2")); - xstat(TESTPATH("file2"), &sb); + xlink("file", "file2"); + xstat("file2", &sb); /* Ensure if inode number and link count is proper */ assert(sb.st_ino == fileino); assert(sb.st_nlink == 2); /* Ensure if data is the same */ - assert_open_ok(1, TESTPATH("file2"), 0, O_RDWR); - assert(read(4, rdbuf, 32) == 32); + assert_open_ok(1, "file2", 0, O_RDWR); + assert(xread(4, rdbuf, 32) == 32); assert(!memcmp(wrbuf, rdbuf, 32)); /* Make another link to the same file*/ - xlink(TESTPATH("file2"), TESTPATH("file3")); - xstat(TESTPATH("file3"), &sb); + xlink("file2", "file3"); + xstat("file3", &sb); /* Ensure if inode number and link count is proper */ assert(sb.st_ino == fileino); assert(sb.st_nlink == 3); - assert_open_ok(2, TESTPATH("file3"), 0, O_RDWR); + assert_open_ok(2, "file3", 0, O_RDWR); /* Make a change to the first file and check for change*/ assert_lseek_ok(0, 0, SEEK_SET); assert_write_ok(0, wrbuf + 32, 32); - assert(read(5, rdbuf, 32) == 32); + assert(xread(5, rdbuf, 32) == 32); assert(!memcmp(wrbuf + 32, rdbuf, 32)); /* Delete second file */ assert_close_ok(1); - xunlink(TESTPATH("file2")); + xunlink("file2"); - xstat(TESTPATH("file"), &sb); + xstat("file", &sb); assert(sb.st_nlink == 2); - xunlink(TESTPATH("file")); + xunlink("file"); - xstat(TESTPATH("file3"), &sb); + xstat("file3", &sb); assert(sb.st_nlink == 1); - xunlink(TESTPATH("file3")); + xunlink("file3"); syscall_fail(link("/tmp", "/tmp/foo"), EPERM); return 0; } -TEST_ADD(vfs_chmod, 0) { +TEST_ADD(vfs_chmod, TF_TMPDIR) { struct stat sb; - assert(xopen(TESTPATH("file"), O_RDWR | O_CREAT, 0) == 3); - xstat(TESTPATH("file"), &sb); + assert(xopen("file", O_RDWR | O_CREAT, 0) == 3); + xstat("file", &sb); assert((sb.st_mode & ALLPERMS) == 0); - xchmod(TESTPATH("file"), DEFFILEMODE); - xstat(TESTPATH("file"), &sb); + xchmod("file", DEFFILEMODE); + xstat("file", &sb); assert((sb.st_mode & ALLPERMS) == DEFFILEMODE); mode_t mode = S_IXGRP | S_IWOTH | S_IRUSR | S_ISUID; - xchmod(TESTPATH("file"), mode); - xstat(TESTPATH("file"), &sb); + xchmod("file", mode); + xstat("file", &sb); assert((sb.st_mode & ALLPERMS) == mode); mode_t lmode = S_IWUSR | S_IRWXU | S_IRWXO; - xsymlink(TESTPATH("file"), TESTPATH("link")); - xlchmod(TESTPATH("link"), lmode); - xstat(TESTPATH("link"), &sb); + xsymlink("file", "link"); + xlchmod("link", lmode); + xstat("link", &sb); assert((sb.st_mode & ALLPERMS) == mode); - xlstat(TESTPATH("link"), &sb); + xlstat("link", &sb); assert((sb.st_mode & ALLPERMS) == lmode); - xunlink(TESTPATH("file")); - xunlink(TESTPATH("link")); + xunlink("file"); + xunlink("link"); return 0; }