From: Tulio A M Mendes Date: Sun, 15 Feb 2026 04:57:35 +0000 (-0300) Subject: test: expand smoke tests from 35 to 41 checks X-Git-Url: https://projects.tadryanom.me/docs/POSIX_ROADMAP.md?a=commitdiff_plain;h=a488b1349d7c90051c5c3160435bf0a437780f10;p=AdrOS.git test: expand smoke tests from 35 to 41 checks New init.elf test cases: - umask: set/get round-trip verification - pipe capacity: F_GETPIPE_SZ / F_SETPIPE_SZ (fixed constant 1033) - waitid: P_PID + WEXITED on forked child - setitimer/getitimer: ITIMER_REAL set, query, cancel - select regfile: select() on regular file returns immediately readable - poll regfile: poll() on regular file returns POLLIN Added syscall wrappers: sys_umask, sys_setitimer, sys_getitimer, sys_waitid Added types: struct timeval, struct itimerval, P_ALL/P_PID/P_PGID/WEXITED smoke_test.exp: 6 new patterns added (41 total) Results: 41/41 smoke, 16/16 battery, 47/47 host tests pass --- diff --git a/tests/smoke_test.exp b/tests/smoke_test.exp index e7897e7..a4815f4 100755 --- a/tests/smoke_test.exp +++ b/tests/smoke_test.exp @@ -77,6 +77,12 @@ set tests { {"alarm SIGALRM" "\\[init\\] alarm/SIGALRM OK"} {"shmget/shmat" "\\[init\\] shmget/shmat/shmdt OK"} {"O_APPEND" "\\[init\\] O_APPEND OK"} + {"umask" "\\[init\\] umask OK"} + {"pipe capacity" "\\[init\\] pipe capacity OK"} + {"waitid" "\\[init\\] waitid OK"} + {"setitimer/getitimer" "\\[init\\] setitimer/getitimer OK"} + {"select regfile" "\\[init\\] select regfile OK"} + {"poll regfile" "\\[init\\] poll regfile OK"} {"hard link" "\\[init\\] hard link OK"} } diff --git a/user/init.c b/user/init.c index d30b2a5..da3db77 100644 --- a/user/init.c +++ b/user/init.c @@ -102,7 +102,11 @@ enum { SYSCALL_ACCESS = 74, SYSCALL_TRUNCATE = 78, SYSCALL_FTRUNCATE = 79, + SYSCALL_UMASK = 75, SYSCALL_ALARM = 83, + SYSCALL_SETITIMER = 92, + SYSCALL_GETITIMER = 93, + SYSCALL_WAITID = 94, }; enum { @@ -112,6 +116,8 @@ enum { enum { F_GETFL = 3, F_SETFL = 4, + F_GETPIPE_SZ = 1032, + F_SETPIPE_SZ = 1033, }; enum { @@ -222,6 +228,30 @@ enum { enum { EAGAIN = 11, EINVAL = 22, + EEXIST = 17, +}; + +enum { + ITIMER_REAL = 0, + ITIMER_VIRTUAL = 1, + ITIMER_PROF = 2, +}; + +struct timeval { + uint32_t tv_sec; + uint32_t tv_usec; +}; + +struct itimerval { + struct timeval it_interval; + struct timeval it_value; +}; + +enum { + P_ALL = 0, + P_PID = 1, + P_PGID = 2, + WEXITED = 4, }; #define S_IFMT 0170000 @@ -912,6 +942,50 @@ static int sys_link(const char* oldpath, const char* newpath) { return __syscall_fix(ret); } +static int sys_umask(uint32_t mask) { + int ret; + __asm__ volatile( + "int $0x80" + : "=a"(ret) + : "a"(SYSCALL_UMASK), "b"(mask) + : "memory" + ); + return ret; +} + +static int sys_setitimer(int which, const struct itimerval* newval, struct itimerval* oldval) { + int ret; + __asm__ volatile( + "int $0x80" + : "=a"(ret) + : "a"(SYSCALL_SETITIMER), "b"(which), "c"(newval), "d"(oldval) + : "memory" + ); + return __syscall_fix(ret); +} + +static int sys_getitimer(int which, struct itimerval* cur) { + int ret; + __asm__ volatile( + "int $0x80" + : "=a"(ret) + : "a"(SYSCALL_GETITIMER), "b"(which), "c"(cur) + : "memory" + ); + return __syscall_fix(ret); +} + +static int sys_waitid(uint32_t idtype, uint32_t id, void* infop, uint32_t options) { + int ret; + __asm__ volatile( + "int $0x80" + : "=a"(ret) + : "a"(SYSCALL_WAITID), "b"(idtype), "c"(id), "d"(infop), "S"(options) + : "memory" + ); + return __syscall_fix(ret); +} + __attribute__((noreturn)) static void sys_exit(int code) { __asm__ volatile( "int $0x80\n" @@ -2699,7 +2773,131 @@ void _start(void) { sys_write(1, "[init] O_APPEND OK\n", (uint32_t)(sizeof("[init] O_APPEND OK\n") - 1)); } - // C15: hard link (skip gracefully if FS doesn't support it) + // C15b: umask + { + int old = sys_umask(0077); + int cur = sys_umask((uint32_t)old); + if (cur != 0077) { + sys_write(1, "[init] umask set/get failed\n", (uint32_t)(sizeof("[init] umask set/get failed\n") - 1)); + sys_exit(1); + } + sys_write(1, "[init] umask OK\n", (uint32_t)(sizeof("[init] umask OK\n") - 1)); + } + + // C16: F_GETPIPE_SZ / F_SETPIPE_SZ + { + int fds[2]; + if (sys_pipe(fds) < 0) { + sys_write(1, "[init] pipe for pipesz failed\n", (uint32_t)(sizeof("[init] pipe for pipesz failed\n") - 1)); + sys_exit(1); + } + int sz = sys_fcntl(fds[0], F_GETPIPE_SZ, 0); + if (sz <= 0) { + sys_write(1, "[init] F_GETPIPE_SZ failed\n", (uint32_t)(sizeof("[init] F_GETPIPE_SZ failed\n") - 1)); + sys_exit(1); + } + int nsz = sys_fcntl(fds[0], F_SETPIPE_SZ, 8192); + if (nsz < 0) { + sys_write(1, "[init] F_SETPIPE_SZ failed\n", (uint32_t)(sizeof("[init] F_SETPIPE_SZ failed\n") - 1)); + sys_exit(1); + } + int sz2 = sys_fcntl(fds[0], F_GETPIPE_SZ, 0); + if (sz2 < 8192) { + sys_write(1, "[init] F_GETPIPE_SZ after set bad\n", (uint32_t)(sizeof("[init] F_GETPIPE_SZ after set bad\n") - 1)); + sys_exit(1); + } + (void)sys_close(fds[0]); + (void)sys_close(fds[1]); + sys_write(1, "[init] pipe capacity OK\n", (uint32_t)(sizeof("[init] pipe capacity OK\n") - 1)); + } + + // C17: waitid (P_PID, WEXITED) + { + int pid = sys_fork(); + if (pid == 0) { + sys_exit(99); + } + if (pid < 0) { + sys_write(1, "[init] waitid fork failed\n", (uint32_t)(sizeof("[init] waitid fork failed\n") - 1)); + sys_exit(1); + } + uint8_t infobuf[128]; + for (uint32_t i = 0; i < 128; i++) infobuf[i] = 0; + int r = sys_waitid(P_PID, (uint32_t)pid, infobuf, WEXITED); + if (r < 0) { + sys_write(1, "[init] waitid failed\n", (uint32_t)(sizeof("[init] waitid failed\n") - 1)); + sys_exit(1); + } + sys_write(1, "[init] waitid OK\n", (uint32_t)(sizeof("[init] waitid OK\n") - 1)); + } + + // C18: setitimer/getitimer (ITIMER_REAL) + { + struct itimerval itv; + itv.it_value.tv_sec = 0; + itv.it_value.tv_usec = 500000; + itv.it_interval.tv_sec = 0; + itv.it_interval.tv_usec = 0; + struct itimerval old; + if (sys_setitimer(ITIMER_REAL, &itv, &old) < 0) { + sys_write(1, "[init] setitimer failed\n", (uint32_t)(sizeof("[init] setitimer failed\n") - 1)); + sys_exit(1); + } + struct itimerval cur; + if (sys_getitimer(ITIMER_REAL, &cur) < 0) { + sys_write(1, "[init] getitimer failed\n", (uint32_t)(sizeof("[init] getitimer failed\n") - 1)); + sys_exit(1); + } + itv.it_value.tv_sec = 0; + itv.it_value.tv_usec = 0; + itv.it_interval.tv_sec = 0; + itv.it_interval.tv_usec = 0; + (void)sys_setitimer(ITIMER_REAL, &itv, 0); + sys_write(1, "[init] setitimer/getitimer OK\n", (uint32_t)(sizeof("[init] setitimer/getitimer OK\n") - 1)); + } + + // C19: select on regular file (should return immediately readable) + { + int fd = sys_open("/bin/init.elf", 0); + if (fd < 0) { + sys_write(1, "[init] select regfile open failed\n", (uint32_t)(sizeof("[init] select regfile open failed\n") - 1)); + sys_exit(1); + } + uint64_t readfds = (1ULL << (uint32_t)fd); + int r = sys_select((uint32_t)(fd + 1), &readfds, 0, 0, 0); + (void)sys_close(fd); + if (r < 0) { + sys_write(1, "[init] select regfile failed\n", (uint32_t)(sizeof("[init] select regfile failed\n") - 1)); + sys_exit(1); + } + sys_write(1, "[init] select regfile OK\n", (uint32_t)(sizeof("[init] select regfile OK\n") - 1)); + } + + // C20: poll on regular file + { + int fd = sys_open("/bin/init.elf", 0); + if (fd < 0) { + sys_write(1, "[init] poll regfile open failed\n", (uint32_t)(sizeof("[init] poll regfile open failed\n") - 1)); + sys_exit(1); + } + struct pollfd pfd; + pfd.fd = fd; + pfd.events = POLLIN; + pfd.revents = 0; + int r = sys_poll(&pfd, 1, 0); + (void)sys_close(fd); + if (r < 0) { + sys_write(1, "[init] poll regfile failed\n", (uint32_t)(sizeof("[init] poll regfile failed\n") - 1)); + sys_exit(1); + } + if (!(pfd.revents & POLLIN)) { + sys_write(1, "[init] poll regfile no POLLIN\n", (uint32_t)(sizeof("[init] poll regfile no POLLIN\n") - 1)); + sys_exit(1); + } + sys_write(1, "[init] poll regfile OK\n", (uint32_t)(sizeof("[init] poll regfile OK\n") - 1)); + } + + // C21: hard link (skip gracefully if FS doesn't support it) { int fd = sys_open("/disk/linkoriginal", O_CREAT | O_TRUNC); if (fd >= 0) {