From 642b5fb0007b64c77d186fcb018d571152ee1d47 Mon Sep 17 00:00:00 2001 From: dzwdz Date: Mon, 14 Aug 2023 18:51:07 +0200 Subject: reorganization: first steps --- src/cmd/tests/kernel/miscsyscall.c | 315 +++++++++++++++++++++++++++++++++++++ 1 file changed, 315 insertions(+) create mode 100644 src/cmd/tests/kernel/miscsyscall.c (limited to 'src/cmd/tests/kernel/miscsyscall.c') diff --git a/src/cmd/tests/kernel/miscsyscall.c b/src/cmd/tests/kernel/miscsyscall.c new file mode 100644 index 0000000..459da2a --- /dev/null +++ b/src/cmd/tests/kernel/miscsyscall.c @@ -0,0 +1,315 @@ +#include "../tests.h" +#include +#include +#include +#include +#include +#include + + +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 = _sys_await()) != ~0) { + test(0 <= ret && ret < 16); + counts[ret]++; + } + + for (int i = 0; i < 16; i++) + test(counts[i] == 1); +} + +static void test_await2(void) { + /* hangs on failure */ + if (!fork()) { + if (!fork()) { + for (;;) _sys_sleep(1000000000); + } else { + exit(123); + } + } + test(_sys_await() == 123); + test(_sys_await() == ~0); /* don't wait for tombstone */ + _sys_filicide(); +} + +static void test_wait2_basic(void) { + struct sys_wait2 data = {0}; + int pid; + pid = fork(); + if (pid == 0) { + exit(420); + } + test(_sys_wait2(-1, 0, &data) == pid); + test(data.status == 420); + test(_sys_wait2(-1, 0, NULL) == -ECHILD); +} + +static void test_pipe(void) { + const char *pipe_msgs[2] = {"hello", "world"}; + hid_t ends[2]; + char buf[16]; + + /* test regular reads / writes */ + test(_sys_pipe(ends, 0) >= 0); + if (!fork()) { + /* those repeated asserts ensure that you can't read/write to the wrong ends */ + test(_sys_read(ends[1], buf, 16, 0) < 0); + test(_sys_write(ends[0], buf, 16, 0, 0) < 0); + + test(5 == _sys_write(ends[1], pipe_msgs[0], 5, -1, 0)); + + test(_sys_read(ends[1], buf, 16, 0) < 0); + test(_sys_write(ends[0], buf, 16, 0, 0) < 0); + + test(5 == _sys_write(ends[1], pipe_msgs[1], 5, -1, 0)); + + exit(0); + } else { + test(_sys_read(ends[1], buf, 16, 0) < 0); + test(_sys_write(ends[0], buf, 16, 0, 0) < 0); + + test(5 == _sys_read(ends[0], buf, 16, 0)); + test(!memcmp(buf, pipe_msgs[0], 5)); + + test(_sys_read(ends[1], buf, 16, 0) < 0); + test(_sys_write(ends[0], buf, 16, 0, 0) < 0); + + test(5 == _sys_read(ends[0], buf, 16, 0)); + test(!memcmp(buf, pipe_msgs[1], 5)); + + _sys_await(); + } + close(ends[0]); + close(ends[1]); + + + /* writing to pipes with one end closed */ + test(_sys_pipe(ends, 0) >= 0); + for (int i = 0; i < 16; i++) { + if (!fork()) { + close(ends[1]); + test(_sys_read(ends[0], buf, 16, 0) < 0); + exit(0); + } + } + close(ends[1]); + for (int i = 0; i < 16; i++) + _sys_await(); + close(ends[0]); + + test(_sys_pipe(ends, 0) >= 0); + for (int i = 0; i < 16; i++) { + if (!fork()) { + close(ends[0]); + test(_sys_write(ends[1], buf, 16, 0, 0) < 0); + exit(0); + } + } + close(ends[0]); + for (int i = 0; i < 16; i++) + _sys_await(); + close(ends[1]); + + + /* queueing */ + test(_sys_pipe(ends, 0) >= 0); + for (int i = 0; i < 16; i++) { + if (!fork()) { + test(_sys_write(ends[1], pipe_msgs[0], 5, -1, 0) == 5); + exit(0); + } + } + close(ends[1]); + for (int i = 0; i < 16; i++) { + test(_sys_read(ends[0], buf, sizeof buf, 0) == 5); + _sys_await(); + } + test(_sys_read(ends[0], buf, sizeof buf, 0) < 0); + close(ends[0]); + + test(_sys_pipe(ends, 0) >= 0); + for (int i = 0; i < 16; i++) { + if (!fork()) { + memset(buf, 0, sizeof buf); + test(_sys_read(ends[0], buf, 5, -1) == 5); + test(!memcmp(buf, pipe_msgs[1], 5)); + exit(0); + } + } + close(ends[0]); + for (int i = 0; i < 16; i++) { + test(_sys_write(ends[1], pipe_msgs[1], 5, -1, 0) == 5); + _sys_await(); + } + test(_sys_write(ends[1], pipe_msgs[1], 5, -1, 0) < 0); + close(ends[1]); + + + // not a to.do detect when all processes that can read are stuck on writing to the pipe and vice versa + // it seems like linux just lets the process hang endlessly. +} + +static void test_memflag(void) { + void *page = (void*)0x77777000; + _sys_memflag(page, 4096, MEMFLAG_PRESENT); // allocate page + memset(page, 77, 4096); // write to it + _sys_memflag(page, 4096, 0); // free it + + if (!fork()) { + memset(page, 11, 4096); // should segfault + exit(0); + } else { + test(_sys_await() != 0); // test if the process crashed + } + + char *pages[4]; + for (size_t i = 0; i < 4; i++) { + pages[i] = _sys_memflag(NULL, 4096, MEMFLAG_FINDFREE); + test(pages[i] == _sys_memflag(NULL, 4096, MEMFLAG_FINDFREE | MEMFLAG_PRESENT)); + if (i > 0) test(pages[i] != pages[i-1]); + *pages[i] = 0x77; + } + + for (size_t i = 0; i < 4; i++) + _sys_memflag(pages, 4096, MEMFLAG_PRESENT); +} + +static void test_dup(void) { + hid_t pipe[2]; + hid_t h1, h2; + test(_sys_pipe(pipe, 0) >= 0); + + if (!fork()) { + close(pipe[0]); + + h1 = _sys_dup(pipe[1], -1, 0); + test(h1 >= 0); + test(h1 != pipe[1]); + h2 = _sys_dup(h1, -1, 0); + test(h2 >= 0); + test(h2 != pipe[1] && h2 != h1); + + _sys_write(pipe[1], "og", 2, 0, 0); + _sys_write(h1, "h1", 2, 0, 0); + _sys_write(h2, "h2", 2, 0, 0); + + close(pipe[1]); + _sys_write(h1, "h1", 2, 0, 0); + _sys_write(h2, "h2", 2, 0, 0); + + test(_sys_dup(h1, pipe[1], 0) == pipe[1]); + test(_sys_dup(h2, pipe[1], 0) == pipe[1]); + test(_sys_dup(h1, pipe[1], 0) == pipe[1]); + test(_sys_dup(h2, pipe[1], 0) == pipe[1]); + close(h1); + close(h2); + + test(_sys_dup(pipe[1], h2, 0) == h2); + _sys_write(h2, "h2", 2, 0, 0); + close(h2); + + test(_sys_dup(pipe[1], h1, 0) == h1); + _sys_write(h1, "h1", 2, 0, 0); + close(h1); + + exit(0); + } else { + char buf[16]; + size_t count = 0; + close(pipe[1]); + while (_sys_read(pipe[0], buf, sizeof buf, 0) >= 0) + count++; + test(count == 7); + _sys_await(); + } + + + close(pipe[0]); +} + +static void test_execbuf(void) { + if (!fork()) { + uint64_t buf[] = { + EXECBUF_SYSCALL, _SYS_EXIT, 123, 0, 0, 0, 0, + }; + _sys_execbuf(buf, sizeof buf); + test_fail(); + } else { + test(_sys_await() == 123); + } +} + +static void test_sleep(void) { + hid_t reader; + FILE *writer; + if (!forkpipe(&writer, &reader)) { + if (!fork()) { + if (!fork()) { + _sys_sleep(100); + fprintf(writer, "1"); + _sys_sleep(200); + fprintf(writer, "3"); + _sys_sleep(200); + fprintf(writer, "5"); + _sys_exit(0); + } + if (!fork()) { + fprintf(writer, "0"); + _sys_sleep(200); + fprintf(writer, "2"); + _sys_sleep(200); + fprintf(writer, "4"); + /* get killed while asleep + * a peaceful death, i suppose. */ + for (;;) _sys_sleep(1000000000); + } + _sys_await(); + _sys_filicide(); + _sys_exit(0); + } + + /* this part checks if, after killing an asleep process, + * other processes can still wake up */ + _sys_sleep(600); + fprintf(writer, "6"); + exit(0); + } else { + const char *expected = "0123456"; + size_t target = strlen(expected); + size_t pos = 0; + for (;;) { + char buf[128]; + long ret = _sys_read(reader, buf, sizeof buf, 0); + if (ret < 0) break; + test(pos + ret <= target); + test(memcmp(buf, expected + pos, ret) == 0); + pos += ret; + } + test(pos == target); + } +} + +static void test_badopen(void) { + test(_sys_open(TMPFILEPATH, strlen(TMPFILEPATH), OPEN_CREATE | OPEN_WRITE) >= 0); + test(_sys_open(TMPFILEPATH, strlen(TMPFILEPATH), OPEN_CREATE) == -EINVAL); +} + +void r_k_miscsyscall(void) { + run_test(test_await); + run_test(test_await2); + run_test(test_wait2_basic); + run_test(test_pipe); + run_test(test_memflag); + run_test(test_dup); + run_test(test_execbuf); + run_test(test_sleep); + run_test(test_badopen); +} -- cgit v1.2.3