From 26dc784103914b9d6ba36e0a96fa4b3af977626f Mon Sep 17 00:00:00 2001 From: dzwdz Date: Thu, 4 Aug 2022 21:43:38 +0200 Subject: user/tests: split the tests by parts of codebase --- src/user/app/tests/tests.c | 307 ++------------------------------------------- 1 file changed, 9 insertions(+), 298 deletions(-) (limited to 'src/user/app/tests/tests.c') diff --git a/src/user/app/tests/tests.c b/src/user/app/tests/tests.c index 5c40bcd..a6e7d52 100644 --- a/src/user/app/tests/tests.c +++ b/src/user/app/tests/tests.c @@ -1,312 +1,23 @@ -#define TEST_MACROS #include "tests.h" -#include -#include -#include #include -#include -#include #include -static void run_forked(void (*fn)()) { +void run_test(void (*fn)()) { if (!fork()) { fn(); exit(0); } else { - /* successful tests must return 0 - * TODO add a better fail msg */ + /* successful tests must return 0 */ if (_syscall_await() != 0) test_fail(); } } - -const char *tmpfilepath = "/tmp/.test_internal"; - -static void test_await(void) { - /* creates 16 child processes, each returning a different value. then checks - * if await() returns every value exactly once */ - int ret; - int counts[16] = {0}; - - for (int i = 0; i < 16; i++) - if (!fork()) - exit(i); - - while ((ret = _syscall_await()) != ~0) { - assert(0 <= ret && ret < 16); - counts[ret]++; - } - - for (int i = 0; i < 16; i++) - assert(counts[i] == 1); -} - -static void test_faults(void) { - /* tests what happens when child processes fault. - * expected behavior: parent processes still manages to finish, and it can - * reap all its children */ - int await_cnt = 0; - - if (!fork()) { // invalid memory access - asm volatile("movb $69, 0" ::: "memory"); - printf("this shouldn't happen"); - exit(-1); - } - if (!fork()) { // #GP - asm volatile("hlt" ::: "memory"); - printf("this shouldn't happen"); - exit(-1); - } - - while (_syscall_await() != ~0) await_cnt++; - assert(await_cnt == 2); -} - -static void test_interrupted_fs(void) { - handle_t h; - if (_syscall_fork(FORK_NEWFS, &h)) { /* child */ - // TODO make a similar test with all 0s passed to fs_wait - struct fs_wait_response res; - _syscall_fs_wait(NULL, 0, &res); - exit(0); - } else { /* parent */ - _syscall_mount(h, "/", 1); - int ret = _syscall_open("/", 1, 0); - // the handler quits while handling that call - but this syscall should return anyways - exit(ret < 0 ? 0 : -1); - } -} - -static void test_orphaned_fs(void) { - handle_t h; - if (_syscall_fork(FORK_NEWFS, &h)) { /* child */ - exit(0); - } else { /* parent */ - _syscall_mount(h, "/", 1); - int ret = _syscall_open("/", 1, 0); - // no handler will ever be available to handle this call - the syscall should instantly return - exit(ret < 0 ? 0 : -1); - } -} - -static void test_memflag(void) { - void *page = (void*)0x77777000; - _syscall_memflag(page, 4096, MEMFLAG_PRESENT); // allocate page - memset(page, 77, 4096); // write to it - _syscall_memflag(page, 4096, 0); // free it - - if (!fork()) { - memset(page, 11, 4096); // should segfault - exit(0); - } else { - assert(_syscall_await() != 0); // test if the process crashed - } - - char *pages[4]; - for (size_t i = 0; i < 4; i++) { - pages[i] = _syscall_memflag(NULL, 4096, MEMFLAG_FINDFREE); - printf("[test_memflag] findfree: 0x%x\n", pages[i]); - - assert(pages[i] == _syscall_memflag(NULL, 4096, MEMFLAG_FINDFREE | MEMFLAG_PRESENT)); - if (i > 0) assert(pages[i] != pages[i-1]); - *pages[i] = 0x77; - } - - for (size_t i = 0; i < 4; i++) - _syscall_memflag(pages, 4096, MEMFLAG_PRESENT); - - // TODO check if reclaims -} - -static void test_dup(void) { - handle_t pipe[2]; - handle_t h1, h2; - assert(_syscall_pipe(pipe, 0) >= 0); - - if (!fork()) { - close(pipe[0]); - - h1 = _syscall_dup(pipe[1], -1, 0); - assert(h1 >= 0); - assert(h1 != pipe[1]); - h2 = _syscall_dup(h1, -1, 0); - assert(h2 >= 0); - assert(h2 != pipe[1] && h2 != h1); - - _syscall_write(pipe[1], "og", 2, 0, 0); - _syscall_write(h1, "h1", 2, 0, 0); - _syscall_write(h2, "h2", 2, 0, 0); - - close(pipe[1]); - _syscall_write(h1, "h1", 2, 0, 0); - _syscall_write(h2, "h2", 2, 0, 0); - - assert(_syscall_dup(h1, pipe[1], 0) == pipe[1]); - assert(_syscall_dup(h2, pipe[1], 0) == pipe[1]); - assert(_syscall_dup(h1, pipe[1], 0) == pipe[1]); - assert(_syscall_dup(h2, pipe[1], 0) == pipe[1]); - close(h1); - close(h2); - - assert(_syscall_dup(pipe[1], h2, 0) == h2); - _syscall_write(h2, "h2", 2, 0, 0); - close(h2); - - assert(_syscall_dup(pipe[1], h1, 0) == h1); - _syscall_write(h1, "h1", 2, 0, 0); - close(h1); - - exit(0); - } else { - char buf[16]; - size_t count = 0; - close(pipe[1]); - while (_syscall_read(pipe[0], buf, sizeof buf, 0) >= 0) - count++; - assert(count == 7); - _syscall_await(); - } - - - close(pipe[0]); -} - -static void test_malloc(void) { - // not really a test - void *p1, *p2; - - p1 = malloc(420); - printf("p1 = 0x%x\n", p1); - - p2 = malloc(1024); - printf("p2 = 0x%x\n", p2); - free(p2); - p2 = malloc(256); - printf("p2 = 0x%x\n", p2); - free(p2); - p2 = malloc(4096); - printf("p2 = 0x%x\n", p2); - free(p2); - - free(p1); -} - -static void test_efault(void) { - const char *str = "o, 16 characters"; - char str2[16]; - char *invalid = (void*)0x1000; - handle_t h; - - memcpy(str2, str, 16); - - assert((h = _syscall_open(tmpfilepath, strlen(tmpfilepath), OPEN_CREATE))); - assert(_syscall_write(h, str, 16, 0, 0) == 16); - assert(_syscall_write(h, str2, 16, 0, 0) == 16); - - assert(_syscall_write(h, invalid, 16, 0, 0) == -EFAULT); - - /* x64 canonical pointers */ - assert(_syscall_write(h, (void*)((uintptr_t)str ^ 0x8000000000000000), 16, 0, 0) == -EFAULT); - assert(_syscall_write(h, (void*)((uintptr_t)str ^ 0x1000000000000000), 16, 0, 0) == -EFAULT); - assert(_syscall_write(h, (void*)((uintptr_t)str ^ 0x0100000000000000), 16, 0, 0) == -EFAULT); - assert(_syscall_write(h, (void*)((uintptr_t)str ^ 0x0010000000000000), 16, 0, 0) == -EFAULT); - assert(_syscall_write(h, (void*)((uintptr_t)str ^ 0x0001000000000000), 16, 0, 0) == -EFAULT); - assert(_syscall_write(h, (void*)((uintptr_t)str ^ 0x0000800000000000), 16, 0, 0) == -EFAULT); - - assert(_syscall_write(h, (void*)((uintptr_t)str2 ^ 0x8000000000000000), 16, 0, 0) == -EFAULT); - assert(_syscall_write(h, (void*)((uintptr_t)str2 ^ 0x1000000000000000), 16, 0, 0) == -EFAULT); - assert(_syscall_write(h, (void*)((uintptr_t)str2 ^ 0x0100000000000000), 16, 0, 0) == -EFAULT); - assert(_syscall_write(h, (void*)((uintptr_t)str2 ^ 0x0010000000000000), 16, 0, 0) == -EFAULT); - assert(_syscall_write(h, (void*)((uintptr_t)str2 ^ 0x0001000000000000), 16, 0, 0) == -EFAULT); - assert(_syscall_write(h, (void*)((uintptr_t)str2 ^ 0x0000800000000000), 16, 0, 0) == -EFAULT); - - assert(_syscall_write(h, str, 16, 0, 0) == 16); - close(h); -} - -static void test_execbuf(void) { - // not really a test, TODO - const char str1[] = "test_execbuf: string 1\n"; - const char str2[] = "test_execbuf: and 2\n"; - uint64_t buf[] = { - EXECBUF_SYSCALL, _SYSCALL_WRITE, 1, (uintptr_t)str1, sizeof(str1) - 1, -1, 0, - EXECBUF_SYSCALL, _SYSCALL_WRITE, 1, (uintptr_t)str2, sizeof(str2) - 1, -1, 0, - EXECBUF_SYSCALL, _SYSCALL_EXIT, 0, 0, 0, 0, 0, - }; - _syscall_execbuf(buf, sizeof buf); - test_fail(); -} - -static void test_strtol(void) { - char *end; - assert(1234 == strtol("1234", NULL, 10)); - assert(1234 == strtol("+1234", NULL, 10)); - assert(-1234 == strtol("-1234", NULL, 10)); - - assert(1234 == strtol("1234", &end, 10)); - assert(!strcmp("", end)); - assert(1234 == strtol(" 1234hello", &end, 10)); - assert(!strcmp("hello", end)); - - assert(1234 == strtol(" 1234hello", &end, 0)); - assert(!strcmp("hello", end)); - assert(0xCAF3 == strtol(" 0xCaF3hello", &end, 0)); - assert(!strcmp("hello", end)); - assert(01234 == strtol(" 01234hello", &end, 0)); - assert(!strcmp("hello", end)); -} - -static void test_sleep(void) { - // TODO yet another of those fake tests that you have to verify by hand - if (!fork()) { - if (!fork()) { - _syscall_sleep(100); - printf("1\n"); - _syscall_sleep(200); - printf("3\n"); - _syscall_sleep(200); - printf("5\n"); - _syscall_exit(0); - } - if (!fork()) { - printf("0\n"); - _syscall_sleep(200); - printf("2\n"); - _syscall_sleep(200); - printf("4\n"); - /* get killed while asleep - * a peaceful death, i suppose. */ - for (;;) _syscall_sleep(1000000000); - } - _syscall_await(); - _syscall_exit(0); - } - - /* this part checks if, after killing an asleep process, other processes can still wake up */ - _syscall_sleep(600); - printf("6\n"); -} - -static void test_misc(void) { - assert(_syscall(~0, 0, 0, 0, 0, 0) < 0); /* try making an invalid syscall */ -} - - int main(void) { - run_forked(test_await); - run_forked(test_faults); - run_forked(test_interrupted_fs); - run_forked(test_orphaned_fs); - run_forked(test_memflag); - run_forked(test_dup); - run_forked(test_malloc); - run_forked(test_pipe); - run_forked(test_semaphore); - run_forked(test_efault); - run_forked(test_execbuf); - run_forked(test_printf); - run_forked(test_strtol); - run_forked(test_sleep); - run_forked(test_misc); - return 1; + r_k_fs(); + r_k_misc(); + r_k_miscsyscall(); + r_libc_esemaphore(); + r_libc_string(); + r_printf(); + return 0; } -- cgit v1.2.3