From d7c14e94afc2928c70ce065982d519f71c430459 Mon Sep 17 00:00:00 2001 From: Wildan M Date: Wed, 25 Mar 2026 03:05:47 +0700 Subject: [PATCH 1/2] Wrap tests in a separate build directory --- tests/.gitignore | 1 + tests/Makefile | 419 +++------------------- tests/Makefile.run.mk | 33 ++ tests/{run_tests.sh => Makefile.tests.mk} | 194 ++++++++-- tests/args.c | 2 +- tests/errno.c | 2 - tests/expected/bins_dynamic/args.stdout | 2 +- tests/expected/bins_dynamic/errno.stdout | 2 - tests/expected/bins_static/args.stdout | 2 +- tests/expected/bins_static/errno.stdout | 2 - tests/src/main.rs | 95 +++-- 11 files changed, 311 insertions(+), 443 deletions(-) create mode 100644 tests/Makefile.run.mk rename tests/{run_tests.sh => Makefile.tests.mk} (50%) mode change 100755 => 100644 diff --git a/tests/.gitignore b/tests/.gitignore index 604e32da6c..f7f5661096 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -1,3 +1,4 @@ +/build_*/ /bins_*/ /gen/ /*.out diff --git a/tests/Makefile b/tests/Makefile index 37203d81f6..9b8322d9b2 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,356 +1,10 @@ include ../config.mk IS_REDOX?=0 +IS_STATIC?=0 +BUILD?=./build_$(TARGET) -# If compiling for Redox, IS_REDOX must be 1 -ifeq ($(IS_REDOX),1) -FAILING_TESTS= -else -# Wrong modified time -FAILING_TESTS := futimens -# Crash, mmap issue -FAILING_TESTS += malloc/usable_size -# Not a FIFO -FAILING_TESTS += mkfifo -# Waitpid had EINTR -FAILING_TESTS += sigchld -# not triggering ERANGE -FAILING_TESTS += stdlib/ptsname -# Hang -FAILING_TESTS += sys_epoll/epollet -# Kernel hit todo! -FAILING_TESTS += sys_mman/fmap -# Hang -FAILING_TESTS += sys_socket/unixpeername -# Task failed successfully? -FAILING_TESTS += signals/pthread_kill-child -# Got EBADF -FAILING_TESTS += unistd/isatty -# Got EINVAL -FAILING_TESTS += unistd/link -# Signal kept unmasked -FAILING_TESTS += sigqueue -# Unwrap hit, written as TODO -FAILING_TESTS += pthread/customstack -# Returning garbage values -FAILING_TESTS += sys_resource/getrusage -# No times.h header -#FAILING_TESTS += time/times -# Outdated test -#FAILING_TESTS += netdb/netdb - -endif - -# Binaries that should generate the same output every time -EXPECT_NAMES=\ - alloca \ - args \ - arpainet \ - assert \ - constructor \ - ctype \ - crypt/blowfish \ - crypt/md5 \ - crypt/pbkdf2 \ - crypt/scrypt \ - crypt/sha256 \ - crypt/sha512 \ - destructor \ - dirent/fdopendir \ - dirent/scandir \ - endian \ - err \ - errno \ - error \ - fcntl/create \ - fcntl/fcntl \ - fcntl/open \ - fcntl/posix_fallocate \ - features \ - fnmatch \ - glob \ - iso646 \ - libgen \ - locale/duplocale \ - locale/newlocale \ - locale/setlocale \ - math \ - regex \ - select \ - setjmp \ - sigaction \ - sigaltstack \ - signal \ - stdio/all \ - stdio/buffer \ - stdio/dprintf \ - stdio/fgets \ - stdio/fputs \ - stdio/fread \ - stdio/freopen \ - stdio/fseek \ - stdio/fwrite \ - stdio/getc_unget \ - stdio/getline \ - stdio/mutex \ - stdio/popen \ - stdio/printf \ - stdio/putc_unlocked \ - stdio/rename \ - stdio/renameat \ - stdio/scanf \ - stdio/setvbuf \ - stdio/sprintf \ - stdio/printf_space_pad \ - stdio/ungetc_ftell \ - stdio/ungetc_multiple \ - stdio/fscanf_offby1 \ - stdio/fscanf \ - stdio/printf_neg_pad \ - stdlib/a64l \ - stdlib/alloc \ - stdlib/atof \ - stdlib/atoi \ - stdlib/div \ - stdlib/env \ - stdlib/getsubopt \ - stdlib/mkostemps \ - stdlib/qsort \ - stdlib/rand \ - stdlib/rand48 \ - stdlib/random \ - stdlib/strtod \ - stdlib/strtol \ - stdlib/strtoul \ - stdlib/system \ - string/mem \ - string/memcpy \ - string/memmem \ - string/strcat \ - string/strchr \ - string/strchrnul \ - string/strcpy \ - string/strcspn \ - string/strlen \ - string/strncmp \ - string/strpbrk \ - string/strrchr \ - string/strspn \ - string/strstr \ - string/strtok \ - string/strtok_r \ - string/strsep \ - string/strsignal \ - string/stpcpy \ - string/stpncpy \ - strings \ - sys_socket/recv \ - sys_socket/recvfrom \ - sys_socket/unixrecv \ - sys_socket/unixrecvfrom \ - sys_socket/unixsocketpair \ - sys_stat/chmod \ - sys_stat/lstat \ - sys_stat/fstatat \ - sys_syslog/syslog \ - time/asctime \ - time/constants \ - time/gmtime \ - time/localtime \ - time/localtime_r \ - time/macros \ - time/mktime \ - time/strftime \ - time/strptime \ - time/time \ - time/timegm \ - time/tzset \ - tls \ - unistd/access \ - unistd/brk \ - unistd/constants \ - unistd/confstr \ - unistd/dup \ - unistd/exec \ - unistd/fchdir \ - unistd/fork \ - unistd/fsync \ - unistd/ftruncate \ - unistd/getopt \ - unistd/getopt_long \ - unistd/pipe \ - unistd/readlinkat \ - unistd/rmdir \ - unistd/sleep \ - unistd/swab \ - unistd/write \ - wchar/fgetwc \ - wchar/fwide \ - wchar/mbrtowc \ - wchar/mbsrtowcs \ - wchar/printf-on-wchars \ - wchar/putwchar \ - wchar/wscanf \ - wchar/ungetwc \ - wchar/wprintf \ - wchar/wcrtomb \ - wchar/wcpcpy \ - wchar/wcpncpy \ - wchar/wcschr \ - wchar/wcscspn \ - wchar/wcsdup \ - wchar/wcsrchr \ - wchar/wcsrtombs \ - wchar/wcsstr \ - wchar/wcstod \ - wchar/wcstok \ - wchar/wcstol \ - wchar/wcstoimax \ - wchar/wcstoumax \ - wchar/wcscasecmp \ - wchar/wcsncasecmp \ - wchar/wcsnlen \ - wchar/wcsnrtombs \ - wchar/wcswidth \ - wctype/towlower \ - wctype/towupper \ - mknod \ - mknodat - -BUILD?=. - -DYNAMIC_ONLY_NAMES=\ - dlfcn \ - dlopen_scopes - -# Binaries that may generate varied output -VARIED_NAMES=\ - dirent/main \ - dirent/posix_getdents \ - includes \ - kill-waitpid \ - limits \ - net/if \ - netdb/getaddrinfo \ - netdb/getaddrinfo_null \ - pthread/timedwait \ - pty/forkpty \ - psignal \ - pwd \ - sa_restart \ - signals/kill-self \ - signals/kill0-self \ - signals/kill-invalid \ - signals/kill-permission \ - signals/killpg-esrch \ - signals/killpg-invalid \ - signals/killpg0-self \ - signals/kill-group \ - signals/kill-child \ - signals/killpg-child \ - signals/killpg-self \ - signals/pthread_kill-invalid \ - signals/pthread_kill-self \ - signals/pthread_kill0-self \ - signals/raise-compliance \ - signals/sigismember-invalid \ - signals/sigismember-valid \ - signals/sigaddset-add \ - signals/sigdelset-delete \ - signals/signal-h \ - signals/signal-h-2 \ - signals/signal-handle_return \ - signals/signal-handler \ - signals/signal-handler2 \ - signals/signal-ignore \ - signals/signal-invalid \ - signals/signal-uncatchable \ - signals/sigprocmask-3 \ - signals/sigprocmask-4 \ - signals/sigprocmask-5 \ - signals/sigprocmask-6 \ - signals/sigprocmask-7 \ - signals/sigprocmask-8 \ - signals/sigprocmask-9 \ - signals/sigprocmask-10 \ - signals/sigprocmask-11 \ - signals/sigpause-invalid \ - signals/sigpause-revert \ - signals/sigpause-suspend \ - signals/sigprocmask-blocksingle \ - signals/sigrelse-1 \ - signals/sigrelse-2 \ - signals/sigrelse-3 \ - signals/sigset-1 \ - signals/sigset-10 \ - signals/sigset-2 \ - signals/sigset-3 \ - signals/sigset-4 \ - signals/sigset-5 \ - signals/sigset-9 \ - stdio/ctermid \ - stdio/tempnam \ - stdio/tmpnam \ - stdlib/bsearch \ - stdlib/mktemp \ - stdlib/realpath \ - sys_epoll/epoll \ - sys_mman/mmap \ - sys_resource/constants \ - sys_socket/getpeername \ - sys_stat/stat \ - sys_statvfs/statvfs \ - sys_utsname/uname \ - time/gettimeofday \ - unistd/chdir \ - unistd/getcwd \ - unistd/gethostname \ - unistd/getid \ - unistd/getpagesize \ - unistd/pathconf \ - unistd/setid \ - unistd/sysconf \ - pthread/main \ - pthread/cleanup \ - pthread/exit \ - pthread/extjoin \ - pthread/once \ - pthread/barrier \ - pthread/rwlock_trylock \ - pthread/rwlock_randtest \ - pthread/mutex_recursive \ - pthread/timeout \ - pthread/tls \ - grp/getgrouplist \ - grp/getgroups \ - grp/getgrgid_r \ - grp/getgrnam_r \ - grp/gr_iter \ - waitpid \ - waitpid_multiple \ - $(FAILING_TESTS) - -# Tests run with `expect` (require a .c file and an .exp file -# that takes the produced binary as the first argument) -EXPECT_INPUT_NAMES=\ - unistd/getpass - -# TODO: Dynamic linking doesn't work with NATIVE_RELIBC=0 -# TODO: Reduce bins_static tests, only execute it when static link difference matters -ifeq ($(IS_REDOX),0) -BINS+=$(patsubst %,$(BUILD)/bins_static/%,$(VARIED_NAMES)) -BINS+=$(patsubst %,$(BUILD)/bins_dynamic/%,$(VARIED_NAMES)) -EXPECT_BINS+=$(patsubst %,$(BUILD)/bins_static/%,$(EXPECT_NAMES)) -EXPECT_BINS+=$(patsubst %,$(BUILD)/bins_dynamic/%,$(EXPECT_NAMES)) -EXPECT_BINS+=$(patsubst %,$(BUILD)/bins_dynamic/%,$(DYNAMIC_ONLY_NAMES)) -EXPECT_INPUT_BINS=$(patsubst %,$(BUILD)/bins_expect_input/%,$(EXPECT_INPUT_NAMES)) -else -# TODO: Not compiling static tests, too heavy for redoxerd -BINS+=$(patsubst %,$(BUILD)/bins_dynamic/%,$(VARIED_NAMES)) -EXPECT_BINS+=$(patsubst %,$(BUILD)/bins_dynamic/%,$(EXPECT_NAMES)) -EXPECT_BINS+=$(patsubst %,$(BUILD)/bins_dynamic/%,$(DYNAMIC_ONLY_NAMES)) -# TODO: EXPECT_INPUT_BINS -endif +include ./Makefile.tests.mk CARGO_TEST?=cargo TEST_RUNNER?= @@ -360,25 +14,37 @@ TEST_RUNNER?= all: $(BINS) clean: - rm -rf bins_* gen *.out + rm -rf $(BUILD)/bins_* $(BUILD)/gen $(BUILD)/target -run: bins_verify/relibc-tests $(BINS) $(EXPECT_BINS) $(EXPECT_INPUT_BINS) - @echo "\033[1;36;49mRunning tests\033[0m" - $(TEST_RUNNER) $< $(patsubst %,-s%,$(BINS)) $(EXPECT_BINS) - for exp in $(EXPECT_INPUT_BINS); \ - do \ - echo "# expect $$(readlink -e $${exp}.exp) $$(readlink -e $${exp}) #"; \ - expect "$$(readlink -e $${exp}.exp)" "$$(readlink -e $${exp})" test args || exit $$?; \ - done +build: $(BUILD)/bins_verify/relibc-tests $(BINS) $(EXPECT_BINS) $(EXPECT_INPUT_BINS) support_build $(BUILD)/expected -run-once: bins_verify/relibc-tests $(BUILD)/$(TESTBIN) - @echo "\033[1;36;49mRunning single test $(TESTBIN) $*\033[0m" - @if [ -f "expected/$(TESTBIN).stdout" ]; then \ - $(TEST_RUNNER) $< $(TESTBIN); \ - else $(TEST_RUNNER) $< -s$(TESTBIN); fi +# "run" and "run-once" does not copy "expected" so the test runner will not pick outdated "expected" file +support_build: $(BUILD)/Makefile $(BUILD)/Makefile.tests.mk $(BUILD)/example_dir -bins_verify/relibc-tests: src/main.rs - $(CARGO_TEST) build --release --bin relibc-tests --out-dir bins_verify -Z unstable-options +run: $(BUILD)/bins_verify/relibc-tests $(BINS) $(EXPECT_BINS) $(EXPECT_INPUT_BINS) support_build + $(MAKE) run -C $(BUILD) + +run-once: $(BUILD)/bins_verify/relibc-tests $(BUILD)/$(TESTBIN) support_build + $(MAKE) run-once -C $(BUILD) TESTBIN=$(TESTBIN) + +$(BUILD)/bins_verify/relibc-tests: src/main.rs + mkdir -p $(BUILD)/bins_verify + $(CARGO_TEST) build --release --bin relibc-tests --artifact-dir $(BUILD)/bins_verify --target-dir $(BUILD)/target -Z unstable-options + rm -rf $(BUILD)/target + +$(BUILD)/Makefile: Makefile.run.mk + cp -a $< "$@" + +$(BUILD)/Makefile.tests.mk: Makefile.tests.mk + cp -a $< "$@" + +$(BUILD)/expected: expected + rm -rf "$@" + cp -a "$<" $(BUILD)/ + +$(BUILD)/example_dir: example_dir + rm -rf "$@" + cp -a "$<" $(BUILD)/ FLAGS=\ -std=c11 \ @@ -405,8 +71,8 @@ SYSROOT_TARGET?=$(SYSROOT) $(SYSROOT): $(MAKE) -C .. sysroot -NATIVE_RELIBC?=0 -ifeq ($(NATIVE_RELIBC),0) +NATIVE_LIBC?=0 +ifeq ($(NATIVE_LIBC),0) FLAGS+=\ -nostdinc \ -nostdlib \ @@ -439,9 +105,22 @@ DYNAMIC_FLAGS+=\ endif DEPS=../sysroot/$(TARGET) -else + +else # ifeq ($(NATIVE_LIBC),1) DYNAMIC_FLAGS+=\ -Wl,-rpath=\$$ORIGIN +ifeq ($(IS_REDOX),0) +# glibc +FLAGS+=\ + -D_POSIX_C_SOURCE=200809L \ + -D_DEFAULT_SOURCE \ + -D_XOPEN_SOURCE=700 \ + -D_GNU_SOURCE \ + -lcrypt \ + -lm +else +# hosted redox, no extra options needed +endif endif $(BUILD)/bins_static/%: %.c $(DEPS) @@ -451,7 +130,7 @@ $(BUILD)/bins_static/%: %.c $(DEPS) $(BUILD)/bins_expect_input/%: %.c %.exp $(DEPS) mkdir -p "$$(dirname "$@")" @$(CC) "$<" -o "$@" $(FLAGS) $(STATIC_FLAGS) - cp $(word 2, "$^") $(addsuffix .exp,"$@") + cp "$*.exp" $(addsuffix .exp,"$@") $(BUILD)/bins_dynamic/%.so: %.c $(DEPS) mkdir -p "$$(dirname "$@")" @@ -477,6 +156,6 @@ $(BUILD)/bins_dynamic/%: %.c $(DEPS) $(BUILD)/gen/includes: includes.c $(DEPS) rm -rf $@.tmp $@ mkdir -p $@.tmp - $(CC) "$<" -H $(FLAGS) $(DYNAMIC_FLAGS) 2> $@.tmp/graph.txt + @$(CC) "$<" -H $(FLAGS) $(DYNAMIC_FLAGS) 2> $@.tmp/graph.txt sed -i 's|$(SYSROOT)/include/||g' $@.tmp/graph.txt mv $@.tmp $@ diff --git a/tests/Makefile.run.mk b/tests/Makefile.run.mk new file mode 100644 index 0000000000..31e93b92e4 --- /dev/null +++ b/tests/Makefile.run.mk @@ -0,0 +1,33 @@ +BUILD?=. +ifeq ($(shell uname),Redox) +IS_REDOX=1 +else +IS_REDOX=0 +endif + +include ./Makefile.tests.mk + +CARGO_TEST?=cargo +TEST_RUNNER?= + +.PHONY: all clean run run-once + +all: run + +clean: + rm -rf $(BUILD)/gen + +run: $(BUILD)/bins_verify/relibc-tests $(BINS) $(EXPECT_BINS) $(EXPECT_INPUT_BINS) + @echo "\033[1;36;49mRunning tests\033[0m" + $(TEST_RUNNER) $< $(patsubst %,-s%,$(BINS)) $(EXPECT_BINS) + for exp in $(EXPECT_INPUT_BINS); \ + do \ + echo "# expect $$(readlink -e $${exp}.exp) $$(readlink -e $${exp}) #"; \ + expect "$$(readlink -e $${exp}.exp)" "$$(readlink -e $${exp})" test args || exit $$?; \ + done + +run-once: $(BUILD)/bins_verify/relibc-tests $(BUILD)/$(TESTBIN) + @echo "\033[1;36;49mRunning single test $(TESTBIN) $*\033[0m" + @if [ -f "expected/$(TESTBIN).stdout" ]; then \ + $(TEST_RUNNER) $< $(BUILD)/$(TESTBIN); \ + else $(TEST_RUNNER) $< -s$(BUILD)/$(TESTBIN); fi diff --git a/tests/run_tests.sh b/tests/Makefile.tests.mk old mode 100755 new mode 100644 similarity index 50% rename from tests/run_tests.sh rename to tests/Makefile.tests.mk index a586ee6b6b..1f591dabc2 --- a/tests/run_tests.sh +++ b/tests/Makefile.tests.mk @@ -1,12 +1,48 @@ -#!/usr/bin/env bash + +# If compiling for Redox, IS_REDOX must be 1 +ifeq ($(IS_REDOX),1) +FAILING_TESTS= +else +# Wrong modified time +FAILING_TESTS := futimens +# Crash, mmap issue +FAILING_TESTS += malloc/usable_size +# Not a FIFO +FAILING_TESTS += mkfifo +# Waitpid had EINTR +FAILING_TESTS += sigchld +# not triggering ERANGE +FAILING_TESTS += stdlib/ptsname +# Hang +FAILING_TESTS += sys_epoll/epollet +# Kernel hit todo! +FAILING_TESTS += sys_mman/fmap +# Hang +FAILING_TESTS += sys_socket/unixpeername +# Task failed successfully? +FAILING_TESTS += signals/pthread_kill-child +# Got EBADF +FAILING_TESTS += unistd/isatty +# Got EINVAL +FAILING_TESTS += unistd/link +# Signal kept unmasked +FAILING_TESTS += sigqueue +# Unwrap hit, written as TODO +FAILING_TESTS += pthread/customstack +# Returning garbage values +FAILING_TESTS += sys_resource/getrusage +# No times.h header +#FAILING_TESTS += time/times +# Outdated test +#FAILING_TESTS += netdb/netdb + +endif # Binaries that should generate the same output every time -EXPECT_NAMES=(\ +EXPECT_NAMES=\ alloca \ - args \ arpainet \ assert \ - constructor \ ctype \ crypt/blowfish \ crypt/md5 \ @@ -14,22 +50,25 @@ EXPECT_NAMES=(\ crypt/scrypt \ crypt/sha256 \ crypt/sha512 \ - destructor \ + dirent/fdopendir \ dirent/scandir \ endian \ - err \ + err \ errno \ error \ fcntl/create \ fcntl/fcntl \ - features \ + fcntl/open \ + fcntl/posix_fallocate \ + features \ fnmatch \ - futimens \ + glob \ + iso646 \ libgen \ - locale \ + locale/duplocale \ + locale/newlocale \ + locale/setlocale \ math \ - netdb/getaddrinfo \ - ptrace \ regex \ select \ setjmp \ @@ -50,7 +89,9 @@ EXPECT_NAMES=(\ stdio/mutex \ stdio/popen \ stdio/printf \ + stdio/putc_unlocked \ stdio/rename \ + stdio/renameat \ stdio/scanf \ stdio/setvbuf \ stdio/sprintf \ @@ -65,9 +106,8 @@ EXPECT_NAMES=(\ stdlib/atof \ stdlib/atoi \ stdlib/div \ - stdlib/env \ + stdlib/getsubopt \ stdlib/mkostemps \ - stdlib/ptsname \ stdlib/qsort \ stdlib/rand \ stdlib/rand48 \ @@ -77,8 +117,11 @@ EXPECT_NAMES=(\ stdlib/strtoul \ stdlib/system \ string/mem \ + string/memcpy \ + string/memmem \ string/strcat \ string/strchr \ + string/strchrnul \ string/strcpy \ string/strcspn \ string/strlen \ @@ -89,24 +132,35 @@ EXPECT_NAMES=(\ string/strstr \ string/strtok \ string/strtok_r \ + string/strsep \ string/strsignal \ + string/stpcpy \ + string/stpncpy \ strings \ - sys_mman \ + sys_socket/recv \ + sys_socket/recvfrom \ + sys_socket/unixrecv \ + sys_socket/unixrecvfrom \ + sys_socket/unixsocketpair \ + sys_stat/chmod \ + sys_stat/lstat \ + sys_stat/fstatat \ + sys_syslog/syslog \ time/asctime \ time/constants \ time/gmtime \ time/localtime \ + time/localtime_r \ time/macros \ time/mktime \ time/strftime \ - time/strptime \ + time/strptime \ time/time \ time/timegm \ time/tzset \ - tls \ unistd/access \ - unistd/brk \ unistd/constants \ + unistd/confstr \ unistd/dup \ unistd/exec \ unistd/fchdir \ @@ -116,11 +170,11 @@ EXPECT_NAMES=(\ unistd/getopt \ unistd/getopt_long \ unistd/pipe \ + unistd/readlinkat \ unistd/rmdir \ - # unistd/sleep \ + unistd/sleep \ unistd/swab \ unistd/write \ - waitpid \ wchar/fgetwc \ wchar/fwide \ wchar/mbrtowc \ @@ -133,6 +187,7 @@ EXPECT_NAMES=(\ wchar/wcrtomb \ wchar/wcpcpy \ wchar/wcpncpy \ + wchar/wcschr \ wchar/wcscspn \ wchar/wcsdup \ wchar/wcsrchr \ @@ -150,24 +205,24 @@ EXPECT_NAMES=(\ wchar/wcswidth \ wctype/towlower \ wctype/towupper \ - mkfifo \ mknod \ - mknodat \ -) - # TODO: Fix these - # netdb/netdb \ + mknodat # Binaries that may generate varied output -STATUS_NAMES=(\ +VARIED_NAMES=\ dirent/main \ + dirent/posix_getdents \ + includes \ + kill-waitpid \ + limits \ net/if \ + netdb/getaddrinfo \ + netdb/getaddrinfo_null \ + pthread/timedwait \ pty/forkpty \ psignal \ pwd \ sa_restart \ - sigchld \ - stdio/ctermid \ - sigqueue \ signals/kill-self \ signals/kill0-self \ signals/kill-invalid \ @@ -175,32 +230,61 @@ STATUS_NAMES=(\ signals/killpg-esrch \ signals/killpg-invalid \ signals/killpg0-self \ + signals/kill-group \ + signals/kill-child \ + signals/killpg-child \ + signals/killpg-self \ signals/pthread_kill-invalid \ + signals/pthread_kill-self \ signals/pthread_kill0-self \ signals/raise-compliance \ signals/sigismember-invalid \ signals/sigismember-valid \ + signals/sigaddset-add \ + signals/sigdelset-delete \ + signals/signal-h \ + signals/signal-h-2 \ signals/signal-handle_return \ signals/signal-handler \ signals/signal-handler2 \ signals/signal-ignore \ signals/signal-invalid \ signals/signal-uncatchable \ + signals/sigprocmask-3 \ + signals/sigprocmask-4 \ + signals/sigprocmask-5 \ signals/sigprocmask-6 \ signals/sigprocmask-7 \ signals/sigprocmask-8 \ signals/sigprocmask-9 \ + signals/sigprocmask-10 \ signals/sigprocmask-11 \ + signals/sigpause-invalid \ + signals/sigpause-revert \ + signals/sigpause-suspend \ signals/sigprocmask-blocksingle \ + signals/sigrelse-1 \ signals/sigrelse-2 \ signals/sigrelse-3 \ + signals/sigset-1 \ + signals/sigset-10 \ + signals/sigset-2 \ + signals/sigset-3 \ + signals/sigset-4 \ + signals/sigset-5 \ + signals/sigset-9 \ + stdio/ctermid \ stdio/tempnam \ stdio/tmpnam \ stdlib/bsearch \ stdlib/mktemp \ stdlib/realpath \ sys_epoll/epoll \ + sys_mman/mmap \ sys_resource/constants \ + sys_socket/getpeername \ + sys_stat/stat \ + sys_statvfs/statvfs \ sys_utsname/uname \ time/gettimeofday \ unistd/chdir \ @@ -208,31 +292,65 @@ STATUS_NAMES=(\ unistd/gethostname \ unistd/getid \ unistd/getpagesize \ - unistd/isatty \ - unistd/link \ unistd/pathconf \ unistd/setid \ - unistd/stat \ unistd/sysconf \ pthread/main \ pthread/cleanup \ + pthread/exit \ pthread/extjoin \ pthread/once \ - pthread/customstack \ pthread/barrier \ pthread/rwlock_trylock \ pthread/rwlock_randtest \ pthread/mutex_recursive \ pthread/timeout \ + pthread/tls \ grp/getgrouplist \ + grp/getgroups \ grp/getgrgid_r \ grp/getgrnam_r \ grp/gr_iter \ -) - # resource/getrusage - # time/times + waitpid \ + waitpid_multiple \ + $(FAILING_TESTS) -EXPECT_BINS=(${EXPECT_NAMES[@]/#/.\/bins_static\/}) -STATUS_BINS=(${STATUS_NAMES[@]/#/-s.\/bins_static\/}) -bins_verify/relibc-tests ${STATUS_BINS[@]} ${EXPECT_BINS[@]} +# Tests that only working with when ld.so exist +DYNAMIC_ONLY_EXPECT_NAMES=\ + dlfcn \ + dlopen_scopes + +# Tests that may produce different result when ld.so absent +STATIC_CHECK_EXPECT_NAMES=\ + args \ + constructor \ + destructor \ + stdlib/env \ + unistd/brk \ + tls + +# Tests run with `expect` (require a .c file and an .exp file +# that takes the produced binary as the first argument) +EXPECT_INPUT_NAMES=\ + unistd/getpass + +# TODO: Dynamic linking doesn't work with NATIVE_LIBC=0 +ifeq ($(IS_STATIC),1) +BINS+=$(patsubst %,$(BUILD)/bins_static/%,$(VARIED_NAMES)) +EXPECT_BINS+=$(patsubst %,$(BUILD)/bins_static/%,$(EXPECT_NAMES)) +EXPECT_BINS+=$(patsubst %,$(BUILD)/bins_static/%,$(STATIC_CHECK_EXPECT_NAMES)) +ifeq ($(IS_REDOX),0) +EXPECT_INPUT_BINS=$(patsubst %,$(BUILD)/bins_expect_input/%,$(EXPECT_INPUT_NAMES)) +endif +else +BINS+=$(patsubst %,$(BUILD)/bins_dynamic/%,$(VARIED_NAMES)) +EXPECT_BINS+=$(patsubst %,$(BUILD)/bins_static/%,$(STATIC_CHECK_EXPECT_NAMES)) +EXPECT_BINS+=$(patsubst %,$(BUILD)/bins_dynamic/%,$(EXPECT_NAMES)) +EXPECT_BINS+=$(patsubst %,$(BUILD)/bins_dynamic/%,$(STATIC_CHECK_EXPECT_NAMES)) +EXPECT_BINS+=$(patsubst %,$(BUILD)/bins_dynamic/%,$(DYNAMIC_ONLY_EXPECT_NAMES)) +ifeq ($(IS_REDOX),0) +# TODO: redoxer does not have "expect" binary +EXPECT_INPUT_BINS=$(patsubst %,$(BUILD)/bins_expect_input/%,$(EXPECT_INPUT_NAMES)) +endif +endif diff --git a/tests/args.c b/tests/args.c index 6dc49d1325..9095e3a451 100644 --- a/tests/args.c +++ b/tests/args.c @@ -4,7 +4,7 @@ #include "test_helpers.h" int main(int argc, char *argv[]) { - for(int i = 0; i < argc; i++) { + for(int i = 1; i < argc; i++) { write(STDOUT_FILENO, argv[i], strlen(argv[i])); write(STDOUT_FILENO, " ", 1); } diff --git a/tests/errno.c b/tests/errno.c index 61b88269c4..29c7df5265 100644 --- a/tests/errno.c +++ b/tests/errno.c @@ -668,8 +668,6 @@ int main(int argc, char **argv) { assert(argc > 0); - puts(argv[0]); - puts(program_invocation_name); puts(program_invocation_short_name); argv[0] = "changed to argv[0]"; diff --git a/tests/expected/bins_dynamic/args.stdout b/tests/expected/bins_dynamic/args.stdout index 9260930aa6..deefb2f3da 100644 --- a/tests/expected/bins_dynamic/args.stdout +++ b/tests/expected/bins_dynamic/args.stdout @@ -1 +1 @@ -./bins_dynamic/args test args +test args diff --git a/tests/expected/bins_dynamic/errno.stdout b/tests/expected/bins_dynamic/errno.stdout index 1ee5a8128d..58419805ea 100644 --- a/tests/expected/bins_dynamic/errno.stdout +++ b/tests/expected/bins_dynamic/errno.stdout @@ -130,8 +130,6 @@ EUSERS macro available EWOULDBLOCK macro available EXDEV macro available EXFULL macro available -./bins_dynamic/errno -./bins_dynamic/errno errno changed to argv[0] changed to program_invocation_name diff --git a/tests/expected/bins_static/args.stdout b/tests/expected/bins_static/args.stdout index 4de9904e91..deefb2f3da 100644 --- a/tests/expected/bins_static/args.stdout +++ b/tests/expected/bins_static/args.stdout @@ -1 +1 @@ -./bins_static/args test args +test args diff --git a/tests/expected/bins_static/errno.stdout b/tests/expected/bins_static/errno.stdout index 0cd6acd956..58419805ea 100644 --- a/tests/expected/bins_static/errno.stdout +++ b/tests/expected/bins_static/errno.stdout @@ -130,8 +130,6 @@ EUSERS macro available EWOULDBLOCK macro available EXDEV macro available EXFULL macro available -./bins_static/errno -./bins_static/errno errno changed to argv[0] changed to program_invocation_name diff --git a/tests/src/main.rs b/tests/src/main.rs index 41c97db275..9d9c099a4c 100644 --- a/tests/src/main.rs +++ b/tests/src/main.rs @@ -3,36 +3,73 @@ use std::{ env, fs, io::{self, Read, Write}, - path::PathBuf, + path::{Path, PathBuf}, process::{self, Command, ExitStatus, Stdio}, sync::mpsc, thread, time::{Duration, Instant}, }; -fn expected(bin: &str, kind: &str, generated: &[u8], status: ExitStatus) -> Result<(), String> { - let mut expected_file = PathBuf::from(format!("expected/{}.{}", bin, kind)); - if !expected_file.exists() { - expected_file = PathBuf::from(format!( - "expected/{}.{}", - bin.replace("bins_static", "").replace("bins_dynamic", ""), - kind - )); +fn find_expected_dir() -> Result { + let mut current_dir = env::current_exe() + .ok() + .and_then(|p| p.parent().map(|parent| parent.to_path_buf())) + .unwrap_or_else(|| PathBuf::from(".")); + + let mut found_expected_dir = None; + + while current_dir.pop() { + let check = current_dir.join("expected"); + if check.is_dir() { + found_expected_dir = Some(check); + break; + } } - let expected = match fs::read(&expected_file) { - Ok(ok) => ok, - Err(err) => { + found_expected_dir.ok_or_else(|| "Could not find 'expected' directory".to_string()) +} + +fn expected( + expected_dir: &Path, + bin: &str, + kind: &str, + generated: &[u8], + status: ExitStatus, +) -> Result<(), String> { + let expect_file = Path::new(bin).with_added_extension(kind); + let components: Vec<_> = expect_file + .components() + .filter_map(|c| c.as_os_str().to_str()) + .rev() + .collect(); + + let mut expected_file = None; + for i in 0..components.len() { + let sub_path: Vec<_> = components[0..=i] + .iter() + .rev() + .map(|s| s.to_string()) + .collect(); + + let check_file = expected_dir.join(sub_path.join("/")); + if check_file.is_file() { + expected_file = Some(fs::read(check_file)); + break; + } + } + + let expect_name = components.first().unwrap(); + let expected = match expected_file { + Some(Ok(ok)) => ok, + Some(Err(err)) => { + return Err(format!("{} failed to read {}: {}", bin, expect_name, err)); + } + None => { if kind == "stderr" { // missing stderr file, assume test expect none emitted vec![] } else { - return Err(format!( - "{} failed to read {}: {}", - bin, - expected_file.display(), - err - )); + return Err(format!("{} expected file not found: {}", bin, expect_name)); } } }; @@ -75,6 +112,7 @@ fn main() { let slowtime = Duration::from_secs(1); let bins: Vec = env::args().skip(1).collect(); let single_test = bins.len() == 1; + let expected_dir = find_expected_dir(); for bin in bins { let status_only = bin.starts_with(STATUS_ONLY); @@ -116,12 +154,8 @@ fn main() { failures.push(failure); break; } - // A pretty rare hang on pthread/barrier which also stops this loop :( - // https://gitlab.redox-os.org/redox-os/relibc/-/issues/238 - if &bin == "./bins_dynamic/pthread/barrier" - || &bin == "./bins_dynamic/pthread/once" - || start_time.elapsed() > slowtime - { + + if start_time.elapsed() > slowtime { println!("# waiting {}ms", start_time.elapsed().as_millis()); } @@ -199,11 +233,20 @@ fn main() { }; if !status_only { - if let Err(failure) = expected(&bin, "stdout", &stdout, exit_status) { + let Ok(expected_dir) = &expected_dir else { + eprintln!("Expected directory not found"); + process::exit(1); + }; + + if let Err(failure) = + expected(expected_dir, &bin, "stdout", &stdout, exit_status) + { println!("{}", failure); failures.push(failure); } - if let Err(failure) = expected(&bin, "stderr", &stderr, exit_status) { + if let Err(failure) = + expected(expected_dir, &bin, "stderr", &stderr, exit_status) + { println!("{}", failure); failures.push(failure); } From 000cd996f3bbd7c823f0a8e1e0b1b8666af0e425 Mon Sep 17 00:00:00 2001 From: Wildan M Date: Wed, 25 Mar 2026 04:16:16 +0700 Subject: [PATCH 2/2] Add more support test files --- check.sh | 2 +- tests/Makefile | 30 ++++++++++++++++++++++++++---- tests/src/main.rs | 15 ++++++++++++--- 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/check.sh b/check.sh index c7fed0e942..b110a69fc7 100755 --- a/check.sh +++ b/check.sh @@ -103,7 +103,7 @@ run_redoxer() { if [ "$IS_HOST" -eq 0 ]; then redoxer toolchain || { echo -e "${RED}Fail: redoxer toolchain for: $target.${NC}" && exit 1; } export CARGO_TEST="redoxer" - export TEST_RUNNER="redoxer exec --folder ../sysroot/$TARGET/:/usr --folder . --" + export TEST_RUNNER="redoxer exec --folder ../../sysroot/$TARGET/:/usr --folder . --" # TODO: Identify hang issue with pthread/barrier and pthread/once tests in multi core to get rid of this limit export REDOXER_QEMU_ARGS="-smp 1" diff --git a/tests/Makefile b/tests/Makefile index 9b8322d9b2..ae485138f4 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -16,12 +16,26 @@ all: $(BINS) clean: rm -rf $(BUILD)/bins_* $(BUILD)/gen $(BUILD)/target -build: $(BUILD)/bins_verify/relibc-tests $(BINS) $(EXPECT_BINS) $(EXPECT_INPUT_BINS) support_build $(BUILD)/expected +build: $(BUILD)/bins_verify/relibc-tests $(BINS) $(EXPECT_BINS) $(EXPECT_INPUT_BINS) support_build -# "run" and "run-once" does not copy "expected" so the test runner will not pick outdated "expected" file -support_build: $(BUILD)/Makefile $(BUILD)/Makefile.tests.mk $(BUILD)/example_dir +support_build: $(BUILD)/expected \ + $(BUILD)/Makefile \ + $(BUILD)/Makefile.tests.mk \ + $(BUILD)/example_dir \ + $(BUILD)/select.c \ + $(BUILD)/stdlib/realpath.c \ + $(BUILD)/stdio/fread.in \ + $(BUILD)/stdio/fscanf_offby1.c \ + $(BUILD)/stdio/fscanf.c \ + $(BUILD)/stdio/stdio.in \ + $(BUILD)/stdio/getline.in \ + $(BUILD)/stdio/ungetc_ftell.c \ + $(BUILD)/sys_stat/stat.c \ + $(BUILD)/unistd/link.c \ + $(BUILD)/wchar/fgetwc.in \ + $(BUILD)/wchar/ungetwc.in -run: $(BUILD)/bins_verify/relibc-tests $(BINS) $(EXPECT_BINS) $(EXPECT_INPUT_BINS) support_build +run: build $(MAKE) run -C $(BUILD) run-once: $(BUILD)/bins_verify/relibc-tests $(BUILD)/$(TESTBIN) support_build @@ -46,6 +60,14 @@ $(BUILD)/example_dir: example_dir rm -rf "$@" cp -a "$<" $(BUILD)/ +$(BUILD)/%.in: %.in + @mkdir -p "$$(dirname "$@")" + cp "$*.in" "$@" + +$(BUILD)/%.c: %.c + @mkdir -p "$$(dirname "$@")" + cp "$*.c" "$@" + FLAGS=\ -std=c11 \ -fno-builtin \ diff --git a/tests/src/main.rs b/tests/src/main.rs index 9d9c099a4c..b3947e1ddc 100644 --- a/tests/src/main.rs +++ b/tests/src/main.rs @@ -10,7 +10,7 @@ use std::{ time::{Duration, Instant}, }; -fn find_expected_dir() -> Result { +fn find_expected_dir() -> Option { let mut current_dir = env::current_exe() .ok() .and_then(|p| p.parent().map(|parent| parent.to_path_buf())) @@ -26,7 +26,16 @@ fn find_expected_dir() -> Result { } } - found_expected_dir.ok_or_else(|| "Could not find 'expected' directory".to_string()) + if found_expected_dir.is_none() { + if let Ok(cwd) = env::current_dir() { + let check = cwd.join("expected"); + if check.is_dir() { + found_expected_dir = Some(check); + } + } + } + + found_expected_dir } fn expected( @@ -233,7 +242,7 @@ fn main() { }; if !status_only { - let Ok(expected_dir) = &expected_dir else { + let Some(expected_dir) = &expected_dir else { eprintln!("Expected directory not found"); process::exit(1); };