From 5ef956634bc894ab1145bf7cc8e500063fda614d Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Mon, 19 Jun 2023 14:56:22 +0800 Subject: selftests/nolibc: add a standalone test report macro The run-user, run and rerun targets use the same test report script, let's add a standalone test report macro for them. This shrinks code lines and simplify the future maintainability. Suggested-by: Willy Tarreau Link: https://lore.kernel.org/lkml/ZIB792FtG6ibOudp@1wt.eu/ Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/Makefile | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/Makefile b/tools/testing/selftests/nolibc/Makefile index 1b7b3c82f8ad..262a9f21d1b4 100644 --- a/tools/testing/selftests/nolibc/Makefile +++ b/tools/testing/selftests/nolibc/Makefile @@ -84,6 +84,10 @@ CFLAGS ?= -Os -fno-ident -fno-asynchronous-unwind-tables -std=c89 \ $(CFLAGS_$(ARCH)) $(CFLAGS_STACKPROTECTOR) LDFLAGS := -s +REPORT ?= awk '/\[OK\][\r]*$$/{p++} /\[FAIL\][\r]*$$/{f++} /\[SKIPPED\][\r]*$$/{s++} \ + END{ printf("%d test(s) passed, %d skipped, %d failed.", p, s, f); \ + if (s+f > 0) printf(" See all results in %s\n", ARGV[1]); else print; }' + help: @echo "Supported targets under selftests/nolibc:" @echo " all call the \"run\" target below" @@ -131,10 +135,7 @@ libc-test: nolibc-test.c # qemu user-land test run-user: nolibc-test $(Q)qemu-$(QEMU_ARCH) ./nolibc-test > "$(CURDIR)/run.out" || : - $(Q)awk '/\[OK\][\r]*$$/{p++} /\[FAIL\][\r]*$$/{f++} /\[SKIPPED\][\r]*$$/{s++} \ - END{ printf("%d test(s) passed, %d skipped, %d failed.", p, s, f); \ - if (s+f > 0) printf(" See all results in %s\n", ARGV[1]); else print; }' \ - $(CURDIR)/run.out + $(Q)$(REPORT) $(CURDIR)/run.out initramfs: nolibc-test $(QUIET_MKDIR)mkdir -p initramfs @@ -150,18 +151,12 @@ kernel: initramfs # run the tests after building the kernel run: kernel $(Q)qemu-system-$(QEMU_ARCH) -display none -no-reboot -kernel "$(srctree)/$(IMAGE)" -serial stdio $(QEMU_ARGS) > "$(CURDIR)/run.out" - $(Q)awk '/\[OK\][\r]*$$/{p++} /\[FAIL\][\r]*$$/{f++} /\[SKIPPED\][\r]*$$/{s++} \ - END{ printf("%d test(s) passed, %d skipped, %d failed.", p, s, f); \ - if (s+f > 0) printf(" See all results in %s\n", ARGV[1]); else print; }' \ - $(CURDIR)/run.out + $(Q)$(REPORT) $(CURDIR)/run.out # re-run the tests from an existing kernel rerun: $(Q)qemu-system-$(QEMU_ARCH) -display none -no-reboot -kernel "$(srctree)/$(IMAGE)" -serial stdio $(QEMU_ARGS) > "$(CURDIR)/run.out" - $(Q)awk '/\[OK\][\r]*$$/{p++} /\[FAIL\][\r]*$$/{f++} /\[SKIPPED\][\r]*$$/{s++} \ - END{ printf("%d test(s) passed, %d skipped, %d failed.", p, s, f); \ - if (s+f > 0) printf(" See all results in %s\n", ARGV[1]); else print; }' \ - $(CURDIR)/run.out + $(Q)$(REPORT) $(CURDIR)/run.out clean: $(call QUIET_CLEAN, sysroot) -- cgit v1.2.3 From b3389e48bf3199607a96240487c78a1fdd4b3e61 Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Mon, 19 Jun 2023 14:57:34 +0800 Subject: selftests/nolibc: always print the path to test log file Even when there is no failure, developers may be still interested in the test log file, especially, string alignment, duplicated print, kernel message and so forth, so, always print the path to test log file. A new line is added for such a print to avoid annoying people who don't care about it when the test pass completely. Suggested-by: Willy Tarreau Link: https://lore.kernel.org/lkml/ZIB792FtG6ibOudp@1wt.eu/ Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/Makefile b/tools/testing/selftests/nolibc/Makefile index 262a9f21d1b4..2a0c3f4fa204 100644 --- a/tools/testing/selftests/nolibc/Makefile +++ b/tools/testing/selftests/nolibc/Makefile @@ -85,8 +85,8 @@ CFLAGS ?= -Os -fno-ident -fno-asynchronous-unwind-tables -std=c89 \ LDFLAGS := -s REPORT ?= awk '/\[OK\][\r]*$$/{p++} /\[FAIL\][\r]*$$/{f++} /\[SKIPPED\][\r]*$$/{s++} \ - END{ printf("%d test(s) passed, %d skipped, %d failed.", p, s, f); \ - if (s+f > 0) printf(" See all results in %s\n", ARGV[1]); else print; }' + END{ printf("%d test(s) passed, %d skipped, %d failed.\n", p, s, f); \ + printf("See all results in %s\n", ARGV[1]); }' help: @echo "Supported targets under selftests/nolibc:" -- cgit v1.2.3 From 5163b8d31eae909f17184cd020ef5785b36c714e Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Mon, 19 Jun 2023 15:01:43 +0800 Subject: selftests/nolibc: restore the failed tests print The commit fa0df56a804b ("selftests/nolibc: also count skipped and failed tests in output") added counting for the skipped and failed tests, but also removed the 'FAIL' results print, let's restore it for it really allow users to learn the failed details without opening the log file. Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/Makefile b/tools/testing/selftests/nolibc/Makefile index 2a0c3f4fa204..000621f21adc 100644 --- a/tools/testing/selftests/nolibc/Makefile +++ b/tools/testing/selftests/nolibc/Makefile @@ -84,7 +84,7 @@ CFLAGS ?= -Os -fno-ident -fno-asynchronous-unwind-tables -std=c89 \ $(CFLAGS_$(ARCH)) $(CFLAGS_STACKPROTECTOR) LDFLAGS := -s -REPORT ?= awk '/\[OK\][\r]*$$/{p++} /\[FAIL\][\r]*$$/{f++} /\[SKIPPED\][\r]*$$/{s++} \ +REPORT ?= awk '/\[OK\][\r]*$$/{p++} /\[FAIL\][\r]*$$/{f++;print} /\[SKIPPED\][\r]*$$/{s++} \ END{ printf("%d test(s) passed, %d skipped, %d failed.\n", p, s, f); \ printf("See all results in %s\n", ARGV[1]); }' -- cgit v1.2.3 From 67eb617a8e1e46ee726d0b2689dd459aab4e5e18 Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Mon, 3 Jul 2023 10:11:08 +0200 Subject: selftests/nolibc: simplify call to ioperm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit 53fcfafa8c5c ("tools/nolibc/unistd: add syscall()") nolibc has support for syscall(2). Use it to get rid of some ifdef-ery. Signed-off-by: Thomas Weißschuh Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index 486334981e60..c02d89953679 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -1051,11 +1051,7 @@ int main(int argc, char **argv, char **envp) * exit with status code 2N+1 when N is written to 0x501. We * hard-code the syscall here as it's arch-dependent. */ -#if defined(_NOLIBC_SYS_H) - else if (my_syscall3(__NR_ioperm, 0x501, 1, 1) == 0) -#else - else if (ioperm(0x501, 1, 1) == 0) -#endif + else if (syscall(__NR_ioperm, 0x501, 1, 1) == 0) __asm__ volatile ("outb %%al, %%dx" :: "d"(0x501), "a"(0)); /* if it does nothing, fall back to the regular panic */ #endif -- cgit v1.2.3 From 938b5b983330a55af8e31eabf329db7dbc7a5038 Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Fri, 7 Jul 2023 23:01:09 +0800 Subject: selftests/nolibc: export argv0 for some tests argv0 is the path to nolibc-test program itself, which is a very good always existing readable file for some tests, let's export it. Note, the path may be absolute or relative, please make sure the tests work with both of them. If it is relative, we must make sure the current path is the one specified by the PWD environment variable. Suggested-by: Willy Tarreau Link: https://lore.kernel.org/lkml/ZKKbS3cwKcHgnGwu@1wt.eu/ Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index c02d89953679..1e4a39548f26 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -43,6 +43,9 @@ /* will be used by nolibc by getenv() */ char **environ; +/* will be used by some test cases as readable file, please don't write it */ +static const char *argv0; + /* definition of a series of tests */ struct test { const char *name; /* test name */ @@ -948,6 +951,7 @@ int main(int argc, char **argv, char **envp) int idx; char *test; + argv0 = argv[0]; environ = envp; /* when called as init, it's possible that no console was opened, for -- cgit v1.2.3 From 82e339c23036d0abefa7ef68d8fb134b0a7f14f4 Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Fri, 7 Jul 2023 23:02:16 +0800 Subject: selftests/nolibc: prepare: create /dev/zero /dev/zero is commonly used to allocate anonymous memory, it is a very good file for tests, let's prepare it. Suggested-by: Willy Tarreau Link: https://lore.kernel.org/lkml/20230702193306.GK16233@1wt.eu/ Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index 1e4a39548f26..24db3be08a15 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -894,11 +894,13 @@ int prepare(void) */ if (stat("/dev/.", &stat_buf) == 0 || mkdir("/dev", 0755) == 0) { if (stat("/dev/console", &stat_buf) != 0 || - stat("/dev/null", &stat_buf) != 0) { + stat("/dev/null", &stat_buf) != 0 || + stat("/dev/zero", &stat_buf) != 0) { /* try devtmpfs first, otherwise fall back to manual creation */ if (mount("/dev", "/dev", "devtmpfs", 0, 0) != 0) { mknod("/dev/console", 0600 | S_IFCHR, makedev(5, 1)); mknod("/dev/null", 0666 | S_IFCHR, makedev(1, 3)); + mknod("/dev/zero", 0666 | S_IFCHR, makedev(1, 5)); } } } -- cgit v1.2.3 From 29f5540be3925d76ef6257d23b1782cdbf55c94f Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Fri, 7 Jul 2023 23:03:26 +0800 Subject: selftests/nolibc: add EXPECT_PTREQ, EXPECT_PTRNE and EXPECT_PTRER The syscalls like sbrk() and mmap() return pointers, to test them, more pointer compare test macros are required, add them: - EXPECT_PTREQ() expects two equal pointers. - EXPECT_PTRNE() expects two non-equal pointers. - EXPECT_PTRER() expects failure with a specified errno. - EXPECT_PTRER2() expects failure with one of two specified errnos. Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 58 ++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index 24db3be08a15..ea22359d3873 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -364,6 +364,64 @@ static int expect_ptrnz(const void *expr, int llen) return ret; } +#define EXPECT_PTREQ(cond, expr, cmp) \ + do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ptreq(expr, llen, cmp); } while (0) + +static int expect_ptreq(const void *expr, int llen, const void *cmp) +{ + int ret = 0; + + llen += printf(" = <%p> ", expr); + if (expr != cmp) { + ret = 1; + llen += pad_spc(llen, 64, "[FAIL]\n"); + } else { + llen += pad_spc(llen, 64, " [OK]\n"); + } + return ret; +} + +#define EXPECT_PTRNE(cond, expr, cmp) \ + do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ptrne(expr, llen, cmp); } while (0) + +static int expect_ptrne(const void *expr, int llen, const void *cmp) +{ + int ret = 0; + + llen += printf(" = <%p> ", expr); + if (expr == cmp) { + ret = 1; + llen += pad_spc(llen, 64, "[FAIL]\n"); + } else { + llen += pad_spc(llen, 64, " [OK]\n"); + } + return ret; +} + +#define EXPECT_PTRER2(cond, expr, expret, experr1, experr2) \ + do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ptrerr2(expr, expret, experr1, experr2, llen); } while (0) + +#define EXPECT_PTRER(cond, expr, expret, experr) \ + EXPECT_PTRER2(cond, expr, expret, experr, 0) + +static int expect_ptrerr2(const void *expr, const void *expret, int experr1, int experr2, int llen) +{ + int ret = 0; + int _errno = errno; + + llen += printf(" = <%p> %s ", expr, errorname(_errno)); + if (expr != expret || (_errno != experr1 && _errno != experr2)) { + ret = 1; + if (experr2 == 0) + llen += printf(" != (<%p> %s) ", expret, errorname(experr1)); + else + llen += printf(" != (<%p> %s %s) ", expret, errorname(experr1), errorname(experr2)); + llen += pad_spc(llen, 64, "[FAIL]\n"); + } else { + llen += pad_spc(llen, 64, " [OK]\n"); + } + return ret; +} #define EXPECT_STRZR(cond, expr) \ do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_strzr(expr, llen); } while (0) -- cgit v1.2.3 From f193ecbff0effc06190036d92ec2fa582d9e6824 Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Fri, 7 Jul 2023 23:04:38 +0800 Subject: selftests/nolibc: add sbrk_0 to test current brk getting >From musl 0.9.14 (to the latest version 1.2.3), both sbrk() and brk() have almost been disabled for they conflict with malloc, only sbrk(0) is still permitted as a way to get the current location of the program break, let's support such case. EXPECT_PTRNE() is used to expect sbrk() always successfully getting the current break. Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 1 + 1 file changed, 1 insertion(+) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index ea22359d3873..5e17e7907379 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -633,6 +633,7 @@ int run_syscall(int min, int max) CASE_TEST(kill_0); EXPECT_SYSZR(1, kill(getpid(), 0)); break; CASE_TEST(kill_CONT); EXPECT_SYSZR(1, kill(getpid(), 0)); break; CASE_TEST(kill_BADPID); EXPECT_SYSER(1, kill(INT_MAX, 0), -1, ESRCH); break; + CASE_TEST(sbrk_0); EXPECT_PTRNE(1, sbrk(0), (void *)-1); break; CASE_TEST(sbrk); if ((p1 = p2 = sbrk(4096)) != (void *)-1) p2 = sbrk(-4096); EXPECT_SYSZR(1, (p2 == (void *)-1) || p2 == p1); break; CASE_TEST(brk); EXPECT_SYSZR(1, brk(sbrk(0))); break; CASE_TEST(chdir_root); EXPECT_SYSZR(1, chdir("/")); break; -- cgit v1.2.3 From d4a3b2b99810ef398c352585edff2c23b17ef86d Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Fri, 7 Jul 2023 23:05:49 +0800 Subject: selftests/nolibc: add mmap_bad test case The length argument of mmap() must be greater than 0, passing a zero length argument expects failure with -EINVAL. Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 1 + 1 file changed, 1 insertion(+) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index 5e17e7907379..39c145b5e03d 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -669,6 +669,7 @@ int run_syscall(int min, int max) CASE_TEST(lseek_m1); EXPECT_SYSER(1, lseek(-1, 0, SEEK_SET), -1, EBADF); break; CASE_TEST(lseek_0); EXPECT_SYSER(1, lseek(0, 0, SEEK_SET), -1, ESPIPE); break; CASE_TEST(mkdir_root); EXPECT_SYSER(1, mkdir("/", 0755), -1, EEXIST); break; + CASE_TEST(mmap_bad); EXPECT_PTRER(1, mmap(NULL, 0, PROT_READ, MAP_PRIVATE, 0, 0), MAP_FAILED, EINVAL); break; CASE_TEST(open_tty); EXPECT_SYSNE(1, tmp = open("/dev/null", 0), -1); if (tmp != -1) close(tmp); break; CASE_TEST(open_blah); EXPECT_SYSER(1, tmp = open("/proc/self/blah", 0), -1, ENOENT); if (tmp != -1) close(tmp); break; CASE_TEST(poll_null); EXPECT_SYSZR(1, poll(NULL, 0, 0)); break; -- cgit v1.2.3 From ba3d0892be0e2d5a7d144c5519920130639524fc Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Fri, 7 Jul 2023 23:07:13 +0800 Subject: selftests/nolibc: add munmap_bad test case The addr argument of munmap() must be a multiple of the page size, passing invalid (void *)1 addr expects failure with -EINVAL. Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 1 + 1 file changed, 1 insertion(+) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index 39c145b5e03d..a11fec00fd01 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -670,6 +670,7 @@ int run_syscall(int min, int max) CASE_TEST(lseek_0); EXPECT_SYSER(1, lseek(0, 0, SEEK_SET), -1, ESPIPE); break; CASE_TEST(mkdir_root); EXPECT_SYSER(1, mkdir("/", 0755), -1, EEXIST); break; CASE_TEST(mmap_bad); EXPECT_PTRER(1, mmap(NULL, 0, PROT_READ, MAP_PRIVATE, 0, 0), MAP_FAILED, EINVAL); break; + CASE_TEST(munmap_bad); EXPECT_SYSER(1, munmap((void *)1, 0), -1, EINVAL); break; CASE_TEST(open_tty); EXPECT_SYSNE(1, tmp = open("/dev/null", 0), -1); if (tmp != -1) close(tmp); break; CASE_TEST(open_blah); EXPECT_SYSER(1, tmp = open("/proc/self/blah", 0), -1, ENOENT); if (tmp != -1) close(tmp); break; CASE_TEST(poll_null); EXPECT_SYSZR(1, poll(NULL, 0, 0)); break; -- cgit v1.2.3 From fcdbf5dda418aad3fdc5fcedbdb41900a24178a8 Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Fri, 7 Jul 2023 23:08:20 +0800 Subject: selftests/nolibc: add mmap_munmap_good test case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mmap() a file with a good offset and then munmap() it. a non-zero offset is passed to test the 6th argument of my_syscall6(). Note, it is not easy to find a unique file for mmap() in different scenes, so, a file list is used to search the right one: - /dev/zero: is commonly used to allocate anonymous memory and is likely present and readable - /proc/1/exe: for 'run' and 'run-user' target, 'run-user' can not find '/proc/self/exe' - /proc/self/exe: for 'libc-test' target, normal program 'libc-test' has no permission to access '/proc/1/exe' - argv0: the path of the program itself, let it pass even with worst case scene: no procfs and no /dev/zero Suggested-by: Willy Tarreau Link: https://lore.kernel.org/lkml/20230702193306.GK16233@1wt.eu/ Suggested-by: Thomas Weißschuh Link: https://lore.kernel.org/lkml/bff82ea6-610b-4471-a28b-6c76c28604a6@t-8ch.de/ Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 60 ++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index a11fec00fd01..84bcc725d8d6 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -595,6 +595,65 @@ static int test_stat_timestamps(void) return 0; } +int test_mmap_munmap(void) +{ + int ret, fd, i; + void *mem; + size_t page_size, file_size, length; + off_t offset, pa_offset; + struct stat stat_buf; + const char * const files[] = { + "/dev/zero", + "/proc/1/exe", "/proc/self/exe", + argv0, + NULL + }; + + page_size = getpagesize(); + if (page_size < 0) + return -1; + + /* find a right file to mmap, existed and accessible */ + for (i = 0; files[i] != NULL; i++) { + ret = fd = open(files[i], O_RDONLY); + if (ret == -1) + continue; + else + break; + } + if (ret == -1) + return ret; + + ret = stat(files[i], &stat_buf); + if (ret == -1) + goto end; + + /* file size of the special /dev/zero is 0, let's assign one manually */ + if (i == 0) + file_size = 3*page_size; + else + file_size = stat_buf.st_size; + + offset = file_size - 1; + if (offset < 0) + offset = 0; + length = file_size - offset; + pa_offset = offset & ~(page_size - 1); + + mem = mmap(NULL, length + offset - pa_offset, PROT_READ, MAP_SHARED, fd, pa_offset); + if (mem == MAP_FAILED) { + ret = -1; + goto end; + } + + ret = munmap(mem, length + offset - pa_offset); + +end: + close(fd); + return ret; +} + + /* Run syscall tests between IDs and . * Return 0 on success, non-zero on failure. */ @@ -671,6 +730,7 @@ int run_syscall(int min, int max) CASE_TEST(mkdir_root); EXPECT_SYSER(1, mkdir("/", 0755), -1, EEXIST); break; CASE_TEST(mmap_bad); EXPECT_PTRER(1, mmap(NULL, 0, PROT_READ, MAP_PRIVATE, 0, 0), MAP_FAILED, EINVAL); break; CASE_TEST(munmap_bad); EXPECT_SYSER(1, munmap((void *)1, 0), -1, EINVAL); break; + CASE_TEST(mmap_munmap_good); EXPECT_SYSZR(1, test_mmap_munmap()); break; CASE_TEST(open_tty); EXPECT_SYSNE(1, tmp = open("/dev/null", 0), -1); if (tmp != -1) close(tmp); break; CASE_TEST(open_blah); EXPECT_SYSER(1, tmp = open("/proc/self/blah", 0), -1, ENOENT); if (tmp != -1) close(tmp); break; CASE_TEST(poll_null); EXPECT_SYSZR(1, poll(NULL, 0, 0)); break; -- cgit v1.2.3 From cfb672f94f6e42ed8a472a1340afc2b41d265731 Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Sat, 8 Jul 2023 02:22:39 +0800 Subject: selftests/nolibc: add run-libc-test target allow run and report glibc or musl based libc-test. Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/Makefile | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/Makefile b/tools/testing/selftests/nolibc/Makefile index 000621f21adc..d408b688b291 100644 --- a/tools/testing/selftests/nolibc/Makefile +++ b/tools/testing/selftests/nolibc/Makefile @@ -132,6 +132,10 @@ nolibc-test: nolibc-test.c sysroot/$(ARCH)/include libc-test: nolibc-test.c $(QUIET_CC)$(CC) -o $@ $< +run-libc-test: libc-test + $(Q)./libc-test > "$(CURDIR)/run.out" || : + $(Q)$(REPORT) $(CURDIR)/run.out + # qemu user-land test run-user: nolibc-test $(Q)qemu-$(QEMU_ARCH) ./nolibc-test > "$(CURDIR)/run.out" || : -- cgit v1.2.3 From 46cf630c53f359bb9cfe7f487c3a878068fd373d Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Sat, 8 Jul 2023 02:23:45 +0800 Subject: selftests/nolibc: stat_fault: silence NULL argument warning with glibc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use another invalid address (void *)1 instead of NULL to silence this compile warning with glibc: $ make libc-test CC libc-test nolibc-test.c: In function ‘run_syscall’: nolibc-test.c:622:49: warning: null argument where non-null required (argument 1) [-Wnonnull] 622 | CASE_TEST(stat_fault); EXPECT_SYSER(1, stat(NULL, &stat_buf), -1, EFAULT); break; | ^~~~ nolibc-test.c:304:79: note: in definition of macro ‘EXPECT_SYSER2’ 304 | do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_syserr2(expr, expret, experr1, experr2, llen); } while (0) | ^~~~ nolibc-test.c:622:33: note: in expansion of macro ‘EXPECT_SYSER’ 622 | CASE_TEST(stat_fault); EXPECT_SYSER(1, stat(NULL, &stat_buf), -1, EFAULT); break; Reviewed-by: Thomas Weißschuh Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index 84bcc725d8d6..78060329ce2a 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -743,7 +743,7 @@ int run_syscall(int min, int max) CASE_TEST(select_stdout); EXPECT_SYSNE(1, ({ fd_set fds; FD_ZERO(&fds); FD_SET(1, &fds); select(2, NULL, &fds, NULL, NULL); }), -1); break; CASE_TEST(select_fault); EXPECT_SYSER(1, select(1, (void *)1, NULL, NULL, 0), -1, EFAULT); break; CASE_TEST(stat_blah); EXPECT_SYSER(1, stat("/proc/self/blah", &stat_buf), -1, ENOENT); break; - CASE_TEST(stat_fault); EXPECT_SYSER(1, stat(NULL, &stat_buf), -1, EFAULT); break; + CASE_TEST(stat_fault); EXPECT_SYSER(1, stat((void *)1, &stat_buf), -1, EFAULT); break; CASE_TEST(stat_timestamps); EXPECT_SYSZR(1, test_stat_timestamps()); break; CASE_TEST(symlink_root); EXPECT_SYSER(1, symlink("/", "/"), -1, EEXIST); break; CASE_TEST(unlink_root); EXPECT_SYSER(1, unlink("/"), -1, EISDIR); break; -- cgit v1.2.3 From 79b4f68e9e245dba34f7acc4e1e26d8df5f9a4f8 Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Sat, 8 Jul 2023 02:25:11 +0800 Subject: selftests/nolibc: gettid: restore for glibc and musl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As the gettid manpage [1] shows, glibc 2.30 has gettid support, so, let's enable the test for glibc >= 2.30. gettid works on musl too. [1]: https://man7.org/linux/man-pages/man2/gettid.2.html Reviewed-by: Thomas Weißschuh Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index 78060329ce2a..d51eac56ceac 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -668,6 +668,7 @@ int run_syscall(int min, int max) int tmp; int ret = 0; void *p1, *p2; + int has_gettid = 1; /* indicates whether or not /proc is mounted */ proc = stat("/proc", &stat_buf) == 0; @@ -675,6 +676,11 @@ int run_syscall(int min, int max) /* this will be used to skip certain tests that can't be run unprivileged */ euid0 = geteuid() == 0; + /* from 2.30, glibc provides gettid() */ +#if defined(__GLIBC_MINOR__) && defined(__GLIBC__) + has_gettid = __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 30); +#endif + for (test = min; test >= 0 && test <= max; test++) { int llen = 0; /* line length */ @@ -684,9 +690,7 @@ int run_syscall(int min, int max) switch (test + __LINE__ + 1) { CASE_TEST(getpid); EXPECT_SYSNE(1, getpid(), -1); break; CASE_TEST(getppid); EXPECT_SYSNE(1, getppid(), -1); break; -#ifdef NOLIBC - CASE_TEST(gettid); EXPECT_SYSNE(1, gettid(), -1); break; -#endif + CASE_TEST(gettid); EXPECT_SYSNE(has_gettid, gettid(), -1); break; CASE_TEST(getpgid_self); EXPECT_SYSNE(1, getpgid(0), -1); break; CASE_TEST(getpgid_bad); EXPECT_SYSER(1, getpgid(-1), -1, ESRCH); break; CASE_TEST(kill_0); EXPECT_SYSZR(1, kill(getpid(), 0)); break; -- cgit v1.2.3 From 5f2de00e2c9ce00708bbf24f70ceda2ed35e9780 Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Sat, 8 Jul 2023 02:26:24 +0800 Subject: selftests/nolibc: add _LARGEFILE64_SOURCE for musl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _GNU_SOURCE Implies _LARGEFILE64_SOURCE in glibc, but in musl, the default configuration doesn't enable _LARGEFILE64_SOURCE. >From include/dirent.h of musl, getdents64 is provided as getdents when _LARGEFILE64_SOURCE is defined. #if defined(_LARGEFILE64_SOURCE) ... #define getdents64 getdents #endif Let's define _LARGEFILE64_SOURCE to fix up this compile error: tools/testing/selftests/nolibc/nolibc-test.c: In function ‘test_getdents64’: tools/testing/selftests/nolibc/nolibc-test.c:453:8: warning: implicit declaration of function ‘getdents64’; did you mean ‘getdents’? [-Wimplicit-function-declaration] 453 | ret = getdents64(fd, (void *)buffer, sizeof(buffer)); | ^~~~~~~~~~ | getdents /usr/bin/ld: /tmp/ccKILm5u.o: in function `test_getdents64': nolibc-test.c:(.text+0xe3e): undefined reference to `getdents64' collect2: error: ld returned 1 exit status Reviewed-by: Thomas Weißschuh Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 1 + 1 file changed, 1 insertion(+) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index d51eac56ceac..60bbc272cdcf 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ #define _GNU_SOURCE +#define _LARGEFILE64_SOURCE /* libc-specific include files * The program may be built in 3 ways: -- cgit v1.2.3 From 989abf1c7bc590969ef1b19b8e64b69423bfacc7 Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Sat, 8 Jul 2023 02:27:40 +0800 Subject: selftests/nolibc: fix up int_fast16/32_t test cases for musl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit musl limits the fast signed int in 32bit, but glibc and nolibc don't, to let such test cases work on musl, let's provide the type based SINT_MAX_OF_TYPE(type) and SINT_MIN_OF_TYPE(type). Suggested-by: Thomas Weißschuh Link: https://lore.kernel.org/lkml/bc635c4f-67fe-4e86-bfdf-bcb4879b928d@t-8ch.de/ Reviewed-by: Thomas Weißschuh Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index 60bbc272cdcf..bc7a54cef42a 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -41,6 +41,10 @@ #endif #endif +/* for the type of int_fast16_t and int_fast32_t, musl differs from glibc and nolibc */ +#define SINT_MAX_OF_TYPE(type) (((type)1 << (sizeof(type) * 8 - 2)) - (type)1 + ((type)1 << (sizeof(type) * 8 - 2))) +#define SINT_MIN_OF_TYPE(type) (-SINT_MAX_OF_TYPE(type) - 1) + /* will be used by nolibc by getenv() */ char **environ; @@ -828,11 +832,11 @@ int run_stdlib(int min, int max) CASE_TEST(limit_int_fast8_max); EXPECT_EQ(1, INT_FAST8_MAX, (int_fast8_t) 0x7f); break; CASE_TEST(limit_int_fast8_min); EXPECT_EQ(1, INT_FAST8_MIN, (int_fast8_t) 0x80); break; CASE_TEST(limit_uint_fast8_max); EXPECT_EQ(1, UINT_FAST8_MAX, (uint_fast8_t) 0xff); break; - CASE_TEST(limit_int_fast16_min); EXPECT_EQ(1, INT_FAST16_MIN, (int_fast16_t) INTPTR_MIN); break; - CASE_TEST(limit_int_fast16_max); EXPECT_EQ(1, INT_FAST16_MAX, (int_fast16_t) INTPTR_MAX); break; + CASE_TEST(limit_int_fast16_min); EXPECT_EQ(1, INT_FAST16_MIN, (int_fast16_t) SINT_MIN_OF_TYPE(int_fast16_t)); break; + CASE_TEST(limit_int_fast16_max); EXPECT_EQ(1, INT_FAST16_MAX, (int_fast16_t) SINT_MAX_OF_TYPE(int_fast16_t)); break; CASE_TEST(limit_uint_fast16_max); EXPECT_EQ(1, UINT_FAST16_MAX, (uint_fast16_t) UINTPTR_MAX); break; - CASE_TEST(limit_int_fast32_min); EXPECT_EQ(1, INT_FAST32_MIN, (int_fast32_t) INTPTR_MIN); break; - CASE_TEST(limit_int_fast32_max); EXPECT_EQ(1, INT_FAST32_MAX, (int_fast32_t) INTPTR_MAX); break; + CASE_TEST(limit_int_fast32_min); EXPECT_EQ(1, INT_FAST32_MIN, (int_fast32_t) SINT_MIN_OF_TYPE(int_fast32_t)); break; + CASE_TEST(limit_int_fast32_max); EXPECT_EQ(1, INT_FAST32_MAX, (int_fast32_t) SINT_MAX_OF_TYPE(int_fast32_t)); break; CASE_TEST(limit_uint_fast32_max); EXPECT_EQ(1, UINT_FAST32_MAX, (uint_fast32_t) UINTPTR_MAX); break; CASE_TEST(limit_int_fast64_min); EXPECT_EQ(1, INT_FAST64_MIN, (int_fast64_t) INT64_MIN); break; CASE_TEST(limit_int_fast64_max); EXPECT_EQ(1, INT_FAST64_MAX, (int_fast64_t) INT64_MAX); break; -- cgit v1.2.3 From 950add280c0b2221f2f28d0595c9c82f40cfe3ed Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Sat, 8 Jul 2023 02:30:58 +0800 Subject: selftests/nolibc: prefer to Since both glibc and musl provide RB_ flags via , and we just add RB_ flags for nolibc, let's use RB_ flags instead of LINUX_REBOOT_ flags and only reserve the required header. This allows compile libc-test for musl libc without the linux headers. Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index bc7a54cef42a..dc080add9637 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -15,7 +15,6 @@ #include #ifndef _NOLIBC_STDIO_H /* standard libcs need more includes */ -#include #include #include #include @@ -1181,7 +1180,7 @@ int main(int argc, char **argv, char **envp) */ printf("Leaving init with final status: %d\n", !!ret); if (ret == 0) - reboot(LINUX_REBOOT_CMD_POWER_OFF); + reboot(RB_POWER_OFF); #if defined(__x86_64__) /* QEMU started with "-device isa-debug-exit -no-reboot" will * exit with status code 2N+1 when N is written to 0x501. We -- cgit v1.2.3 From c388c9920da2679f62bec48d00ca9e80e9d0a364 Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Sat, 8 Jul 2023 02:32:05 +0800 Subject: selftests/nolibc: fix up kernel parameters support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit kernel parameters allow pass two types of strings, one type is like 'noapic', another type is like 'panic=5', the first type is passed as arguments of the init program, the second type is passed as environment variables of the init program. when users pass kernel parameters like this: noapic NOLIBC_TEST=syscall our nolibc-test program will use the test setting from argv[1] and ignore the one from NOLIBC_TEST environment variable, and at last, it will print the following line and ignore the whole test setting. Ignoring unknown test name 'noapic' reversing the parsing order does solve the above issue: test = getenv("NOLIBC_TEST"); if (test) test = argv[1]; but it still doesn't work with such kernel parameters (without NOLIBC_TEST environment variable): noapic FOO=bar To support all of the potential kernel parameters, let's verify the test setting from both of argv[1] and NOLIBC_TEST environment variable. Reviewed-by: Thomas Weißschuh Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 33 ++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index dc080add9637..c15a4211ff26 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -1073,6 +1073,35 @@ static const struct test test_names[] = { { 0 } }; +int is_setting_valid(char *test) +{ + int idx, len, test_len, valid = 0; + char delimiter; + + if (!test) + return valid; + + test_len = strlen(test); + + for (idx = 0; test_names[idx].name; idx++) { + len = strlen(test_names[idx].name); + if (test_len < len) + continue; + + if (strncmp(test, test_names[idx].name, len) != 0) + continue; + + delimiter = test[len]; + if (delimiter != ':' && delimiter != ',' && delimiter != '\0') + continue; + + valid = 1; + break; + } + + return valid; +} + int main(int argc, char **argv, char **envp) { int min = 0; @@ -1099,10 +1128,10 @@ int main(int argc, char **argv, char **envp) * syscall:5-15[:.*],stdlib:8-10 */ test = argv[1]; - if (!test) + if (!is_setting_valid(test)) test = getenv("NOLIBC_TEST"); - if (test) { + if (is_setting_valid(test)) { char *comma, *colon, *dash, *value; do { -- cgit v1.2.3 From f7a419e35ba3c6301fa096370548599853ef2b5d Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Sat, 8 Jul 2023 02:33:13 +0800 Subject: selftests/nolibc: link_cross: use /proc/self/cmdline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For CONFIG_NET=n, there would be no /proc/self/net, so, use /proc/self/cmdline instead. Reviewed-by: Thomas Weißschuh Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index c15a4211ff26..76b1f7a27c86 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -732,7 +732,7 @@ int run_syscall(int min, int max) CASE_TEST(link_root1); EXPECT_SYSER(1, link("/", "/"), -1, EEXIST); break; CASE_TEST(link_blah); EXPECT_SYSER(1, link("/proc/self/blah", "/blah"), -1, ENOENT); break; CASE_TEST(link_dir); EXPECT_SYSER(euid0, link("/", "/blah"), -1, EPERM); break; - CASE_TEST(link_cross); EXPECT_SYSER(proc, link("/proc/self/net", "/blah"), -1, EXDEV); break; + CASE_TEST(link_cross); EXPECT_SYSER(proc, link("/proc/self/cmdline", "/blah"), -1, EXDEV); break; CASE_TEST(lseek_m1); EXPECT_SYSER(1, lseek(-1, 0, SEEK_SET), -1, EBADF); break; CASE_TEST(lseek_0); EXPECT_SYSER(1, lseek(0, 0, SEEK_SET), -1, ESPIPE); break; CASE_TEST(mkdir_root); EXPECT_SYSER(1, mkdir("/", 0755), -1, EEXIST); break; -- cgit v1.2.3 From 4e14e84442fe59fbe677ff4c328a3075bf514e26 Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Sat, 8 Jul 2023 02:35:38 +0800 Subject: selftests/nolibc: add a new rmdir() test case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A new rmdir_blah test case is added to remove a non-existing /blah, which expects failure with ENOENT errno. Reviewed-by: Thomas Weißschuh Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 1 + 1 file changed, 1 insertion(+) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index 76b1f7a27c86..bb39a1e7fd46 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -746,6 +746,7 @@ int run_syscall(int min, int max) CASE_TEST(poll_fault); EXPECT_SYSER(1, poll((void *)1, 1, 0), -1, EFAULT); break; CASE_TEST(prctl); EXPECT_SYSER(1, prctl(PR_SET_NAME, (unsigned long)NULL, 0, 0, 0), -1, EFAULT); break; CASE_TEST(read_badf); EXPECT_SYSER(1, read(-1, &tmp, 1), -1, EBADF); break; + CASE_TEST(rmdir_blah); EXPECT_SYSER(1, rmdir("/blah"), -1, ENOENT); break; CASE_TEST(sched_yield); EXPECT_SYSZR(1, sched_yield()); break; CASE_TEST(select_null); EXPECT_SYSZR(1, ({ struct timeval tv = { 0 }; select(0, NULL, NULL, NULL, &tv); })); break; CASE_TEST(select_stdout); EXPECT_SYSNE(1, ({ fd_set fds; FD_ZERO(&fds); FD_SET(1, &fds); select(2, NULL, &fds, NULL, NULL); }), -1); break; -- cgit v1.2.3 From b8b26108e4d5a0d004393e8a53d374b2b076ba20 Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Sat, 8 Jul 2023 02:37:45 +0800 Subject: selftests/nolibc: fix up failures when CONFIG_PROC_FS=n MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For CONFIG_PROC_FS=n, the /proc is not mountable, but the /proc directory has been created in the prepare() stage whenever /proc is there or not. so, the checking of /proc in the run_syscall() stage will be always true and at last it will fail all of the procfs dependent test cases, which deviates from the 'cond' check design of the EXPECT_xx macros, without procfs, these test cases should be skipped instead of failed. To solve this issue, one method is checking /proc/self instead of /proc, another method is removing the /proc directory completely for CONFIG_PROC_FS=n, we apply the second method to avoid misleading the users. Reviewed-by: Thomas Weißschuh Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index bb39a1e7fd46..55cc2296c292 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -1057,8 +1057,11 @@ int prepare(void) /* try to mount /proc if not mounted. Silently fail otherwise */ if (stat("/proc/.", &stat_buf) == 0 || mkdir("/proc", 0755) == 0) { - if (stat("/proc/self", &stat_buf) != 0) - mount("/proc", "/proc", "proc", 0, 0); + if (stat("/proc/self", &stat_buf) != 0) { + /* If not mountable, remove /proc completely to avoid misuse */ + if (mount("none", "/proc", "proc", 0, 0) != 0) + rmdir("/proc"); + } } return 0; -- cgit v1.2.3 From bbb14546bd22b1c41af7182d085abe89ae21eecd Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Sat, 8 Jul 2023 02:38:57 +0800 Subject: selftests/nolibc: prepare /tmp for tests that need to write MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit create a /tmp directory. If it succeeds, the directory is writable, which is normally the case when booted from an initramfs anyway. This will be used instead of procfs for some tests. Reviewed-by: Thomas Weißschuh Signed-off-by: Zhangjin Wu Link: https://lore.kernel.org/lkml/20230710050600.9697-1-falcon@tinylab.org/ [wt: removed the unneeded mount() call] Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index 55cc2296c292..bc2f40c9cee6 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -1064,6 +1064,9 @@ int prepare(void) } } + /* some tests rely on a writable /tmp */ + mkdir("/tmp", 0755); + return 0; } -- cgit v1.2.3 From 6861b1a3398ec3f1b830d7d190a6ffbc3be8ab6b Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Sat, 8 Jul 2023 02:40:08 +0800 Subject: selftests/nolibc: vfprintf: remove MEMFD_CREATE dependency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The vfprintf test case require to open a temporary file to write, the old memfd_create() method is perfect but has strong dependency on MEMFD_CREATE and also TMPFS or HUGETLBFS (see fs/Kconfig): config MEMFD_CREATE def_bool TMPFS || HUGETLBFS And from v6.2, MFD_NOEXEC_SEAL must be passed for the non-executable memfd, otherwise, The kernel warning will be output to the test result like this: Running test 'vfprintf' 0 emptymemfd_create() without MFD_EXEC nor MFD_NOEXEC_SEAL, pid=1 'init' "" = "" [OK] To avoid such warning and also to remove the MEMFD_CREATE dependency, let's open a file from tmpfs directly. The /tmp directory is used to detect the existing of tmpfs, if not there, skip instead of fail. And further, for pid == 1, the initramfs is loaded as ramfs, which can be used as tmpfs, so, it is able to further remove TMPFS dependency too. Suggested-by: Thomas Weißschuh Link: https://lore.kernel.org/lkml/9ad51430-b7c0-47dc-80af-20c86539498d@t-8ch.de Reviewed-by: Thomas Weißschuh Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index bc2f40c9cee6..ad1f6358b253 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -876,10 +876,10 @@ static int expect_vfprintf(int llen, size_t c, const char *expected, const char FILE *memfile; va_list args; - fd = memfd_create("vfprintf", 0); + fd = open("/tmp", O_TMPFILE | O_EXCL | O_RDWR, 0600); if (fd == -1) { - pad_spc(llen, 64, "[FAIL]\n"); - return 1; + pad_spc(llen, 64, "[SKIPPED]\n"); + return 0; } memfile = fdopen(fd, "w+"); -- cgit v1.2.3 From 38fc0a3553ced0158d97047f5fb3b73898226a3c Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Sat, 8 Jul 2023 02:42:01 +0800 Subject: selftests/nolibc: chdir_root: restore current path after test The PWD environment variable has the path of the nolibc-test program, the current path must be the same as it, otherwise, the test cases will fail with relative path (e.g. ./nolibc-test). Since only chdir_root really changes the current path, let's restore it with the PWD environment variable. Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index ad1f6358b253..64fca7c6ca49 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -703,7 +703,7 @@ int run_syscall(int min, int max) CASE_TEST(sbrk_0); EXPECT_PTRNE(1, sbrk(0), (void *)-1); break; CASE_TEST(sbrk); if ((p1 = p2 = sbrk(4096)) != (void *)-1) p2 = sbrk(-4096); EXPECT_SYSZR(1, (p2 == (void *)-1) || p2 == p1); break; CASE_TEST(brk); EXPECT_SYSZR(1, brk(sbrk(0))); break; - CASE_TEST(chdir_root); EXPECT_SYSZR(1, chdir("/")); break; + CASE_TEST(chdir_root); EXPECT_SYSZR(1, chdir("/")); chdir(getenv("PWD")); break; CASE_TEST(chdir_dot); EXPECT_SYSZR(1, chdir(".")); break; CASE_TEST(chdir_blah); EXPECT_SYSER(1, chdir("/blah"), -1, ENOENT); break; CASE_TEST(chmod_net); EXPECT_SYSZR(proc, chmod("/proc/self/net", 0555)); break; -- cgit v1.2.3 From f576d3c075dbc469480e737a97916be3c8f1a723 Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Sat, 8 Jul 2023 02:43:44 +0800 Subject: selftests/nolibc: stat_timestamps: remove procfs dependency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit '/proc/self/' is a good path which doesn't have stale time info but it is only available for CONFIG_PROC_FS=y. When CONFIG_PROC_FS=n, use argv0 instead of '/proc/self', use '/' for the worst case. Reviewed-by: Thomas Weißschuh Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index 64fca7c6ca49..d7a84ef10bba 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -584,7 +584,7 @@ static int test_stat_timestamps(void) if (sizeof(st.st_atim.tv_sec) != sizeof(st.st_atime)) return 1; - if (stat("/proc/self/", &st)) + if (stat("/proc/self/", &st) && stat(argv0, &st) && stat("/", &st)) return 1; if (st.st_atim.tv_sec != st.st_atime || st.st_atim.tv_nsec > 1000000000) -- cgit v1.2.3 From 135b622e4855981cad487aead7e6992358a0d25c Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Sat, 8 Jul 2023 02:45:08 +0800 Subject: selftests/nolibc: chroot_exe: remove procfs dependency Since argv0 also works for CONFIG_PROC_FS=n, let's use it instead of '/proc/self/exe'. Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index d7a84ef10bba..be9f664c8435 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -711,7 +711,7 @@ int run_syscall(int min, int max) CASE_TEST(chown_self); EXPECT_SYSER(proc, chown("/proc/self", 0, 0), -1, EPERM); break; CASE_TEST(chroot_root); EXPECT_SYSZR(euid0, chroot("/")); break; CASE_TEST(chroot_blah); EXPECT_SYSER(1, chroot("/proc/self/blah"), -1, ENOENT); break; - CASE_TEST(chroot_exe); EXPECT_SYSER(proc, chroot("/proc/self/exe"), -1, ENOTDIR); break; + CASE_TEST(chroot_exe); EXPECT_SYSER(1, chroot(argv0), -1, ENOTDIR); break; CASE_TEST(close_m1); EXPECT_SYSER(1, close(-1), -1, EBADF); break; CASE_TEST(close_dup); EXPECT_SYSZR(1, close(dup(0))); break; CASE_TEST(dup_0); tmp = dup(0); EXPECT_SYSNE(1, tmp, -1); close(tmp); break; -- cgit v1.2.3 From 148e9718e2a288ef4fee16089cb9555414052fbb Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Sat, 8 Jul 2023 02:46:20 +0800 Subject: selftests/nolibc: add chmod_argv0 test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit argv0 is readable and chmodable, let's use it for chmod test, but a safe umask should be used, the readable and executable modes should be reserved. Reviewed-by: Thomas Weißschuh Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 1 + 1 file changed, 1 insertion(+) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index be9f664c8435..6c94e491e2f8 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -706,6 +706,7 @@ int run_syscall(int min, int max) CASE_TEST(chdir_root); EXPECT_SYSZR(1, chdir("/")); chdir(getenv("PWD")); break; CASE_TEST(chdir_dot); EXPECT_SYSZR(1, chdir(".")); break; CASE_TEST(chdir_blah); EXPECT_SYSER(1, chdir("/blah"), -1, ENOENT); break; + CASE_TEST(chmod_argv0); EXPECT_SYSZR(1, chmod(argv0, 0555)); break; CASE_TEST(chmod_net); EXPECT_SYSZR(proc, chmod("/proc/self/net", 0555)); break; CASE_TEST(chmod_self); EXPECT_SYSER(proc, chmod("/proc/self", 0555), -1, EPERM); break; CASE_TEST(chown_self); EXPECT_SYSER(proc, chown("/proc/self", 0, 0), -1, EPERM); break; -- cgit v1.2.3 From c0315c79aaa23958fbe82c218be2ba3635749769 Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Thu, 6 Jul 2023 17:03:34 +0800 Subject: selftests/nolibc: report: print a summarized test status one of the test status: success, warning and failure is printed to summarize the passed, skipped and failed values. - "success" means no skipped and no failed. - "warning" means has at least one skipped and no failed. - "failure" means all tests are failed. Suggested-by: Willy Tarreau Link: https://lore.kernel.org/lkml/20230702164358.GB16233@1wt.eu/ Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/Makefile b/tools/testing/selftests/nolibc/Makefile index d408b688b291..84b9a46ad678 100644 --- a/tools/testing/selftests/nolibc/Makefile +++ b/tools/testing/selftests/nolibc/Makefile @@ -85,7 +85,8 @@ CFLAGS ?= -Os -fno-ident -fno-asynchronous-unwind-tables -std=c89 \ LDFLAGS := -s REPORT ?= awk '/\[OK\][\r]*$$/{p++} /\[FAIL\][\r]*$$/{f++;print} /\[SKIPPED\][\r]*$$/{s++} \ - END{ printf("%d test(s) passed, %d skipped, %d failed.\n", p, s, f); \ + END{ printf("%d test(s) passed, %d skipped, %d failed => status: ", p, s, f); \ + if (f) printf("failure\n"); else if (s) printf("warning\n"); else printf("success\n");; \ printf("See all results in %s\n", ARGV[1]); }' help: -- cgit v1.2.3 From c0faa0dace195789d50173966f6b1d5f4ceae498 Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Thu, 6 Jul 2023 17:08:16 +0800 Subject: selftests/nolibc: report: print total tests Let's count and print the total number of tests, now, the data of passed, skipped and failed have the same format. Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/Makefile b/tools/testing/selftests/nolibc/Makefile index 84b9a46ad678..a02be8b0a569 100644 --- a/tools/testing/selftests/nolibc/Makefile +++ b/tools/testing/selftests/nolibc/Makefile @@ -85,7 +85,7 @@ CFLAGS ?= -Os -fno-ident -fno-asynchronous-unwind-tables -std=c89 \ LDFLAGS := -s REPORT ?= awk '/\[OK\][\r]*$$/{p++} /\[FAIL\][\r]*$$/{f++;print} /\[SKIPPED\][\r]*$$/{s++} \ - END{ printf("%d test(s) passed, %d skipped, %d failed => status: ", p, s, f); \ + END{ printf("%d test(s): %d passed, %d skipped, %d failed => status: ", p+s+f, p, s, f); \ if (f) printf("failure\n"); else if (s) printf("warning\n"); else printf("success\n");; \ printf("See all results in %s\n", ARGV[1]); }' -- cgit v1.2.3 From 0ac908e304030d04b0df49fda9f216ffa204a527 Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Thu, 6 Jul 2023 17:10:08 +0800 Subject: selftests/nolibc: report: align passed, skipped and failed align the test values for different runs and different architectures. Since the total number of tests is not bigger than 1000 currently, let's align them with "%3d". Signed-off-by: Zhangjin Wu [wt: s/%03d/%3d/ as discussed with Zhangjin] Link: https://lore.kernel.org/lkml/20230709185112.97236-1-falcon@tinylab.org/ Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/Makefile b/tools/testing/selftests/nolibc/Makefile index a02be8b0a569..bb23c5790520 100644 --- a/tools/testing/selftests/nolibc/Makefile +++ b/tools/testing/selftests/nolibc/Makefile @@ -85,7 +85,7 @@ CFLAGS ?= -Os -fno-ident -fno-asynchronous-unwind-tables -std=c89 \ LDFLAGS := -s REPORT ?= awk '/\[OK\][\r]*$$/{p++} /\[FAIL\][\r]*$$/{f++;print} /\[SKIPPED\][\r]*$$/{s++} \ - END{ printf("%d test(s): %d passed, %d skipped, %d failed => status: ", p+s+f, p, s, f); \ + END{ printf("%3d test(s): %3d passed, %3d skipped, %3d failed => status: ", p+s+f, p, s, f); \ if (f) printf("failure\n"); else if (s) printf("warning\n"); else printf("success\n");; \ printf("See all results in %s\n", ARGV[1]); }' -- cgit v1.2.3 From 7d92e89363755978c616c8d9d9f8961989e62be8 Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Thu, 6 Jul 2023 17:11:17 +0800 Subject: selftests/nolibc: report: extrude the test status line two newlines are added around the test summary line to extrude the test status. Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/Makefile b/tools/testing/selftests/nolibc/Makefile index bb23c5790520..1da4e07f0b3b 100644 --- a/tools/testing/selftests/nolibc/Makefile +++ b/tools/testing/selftests/nolibc/Makefile @@ -85,9 +85,9 @@ CFLAGS ?= -Os -fno-ident -fno-asynchronous-unwind-tables -std=c89 \ LDFLAGS := -s REPORT ?= awk '/\[OK\][\r]*$$/{p++} /\[FAIL\][\r]*$$/{f++;print} /\[SKIPPED\][\r]*$$/{s++} \ - END{ printf("%3d test(s): %3d passed, %3d skipped, %3d failed => status: ", p+s+f, p, s, f); \ + END{ printf("\n%3d test(s): %3d passed, %3d skipped, %3d failed => status: ", p+s+f, p, s, f); \ if (f) printf("failure\n"); else if (s) printf("warning\n"); else printf("success\n");; \ - printf("See all results in %s\n", ARGV[1]); }' + printf("\nSee all results in %s\n", ARGV[1]); }' help: @echo "Supported targets under selftests/nolibc:" -- cgit v1.2.3 From 4beb9be811d7c20b3b5ae8c07720d8f5cf066e1e Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Thu, 6 Jul 2023 17:12:28 +0800 Subject: selftests/nolibc: report: add newline before test failures a newline is inserted just before the test failures to avoid mixing the test failures with the raw test log. Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/Makefile b/tools/testing/selftests/nolibc/Makefile index 1da4e07f0b3b..d31d6cea82e2 100644 --- a/tools/testing/selftests/nolibc/Makefile +++ b/tools/testing/selftests/nolibc/Makefile @@ -84,7 +84,7 @@ CFLAGS ?= -Os -fno-ident -fno-asynchronous-unwind-tables -std=c89 \ $(CFLAGS_$(ARCH)) $(CFLAGS_STACKPROTECTOR) LDFLAGS := -s -REPORT ?= awk '/\[OK\][\r]*$$/{p++} /\[FAIL\][\r]*$$/{f++;print} /\[SKIPPED\][\r]*$$/{s++} \ +REPORT ?= awk '/\[OK\][\r]*$$/{p++} /\[FAIL\][\r]*$$/{if (!f) printf("\n"); f++; print;} /\[SKIPPED\][\r]*$$/{s++} \ END{ printf("\n%3d test(s): %3d passed, %3d skipped, %3d failed => status: ", p+s+f, p, s, f); \ if (f) printf("failure\n"); else if (s) printf("warning\n"); else printf("success\n");; \ printf("\nSee all results in %s\n", ARGV[1]); }' -- cgit v1.2.3 From 67d108e2a2bd258b49902ea9d85c25a53a7c5e5b Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Mon, 10 Jul 2023 20:01:34 +0200 Subject: tools/nolibc: completely remove optional environ support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 52e423f5b93e ("tools/nolibc: export environ as a weak symbol on i386") and friends the asm startup logic was extended to directly populate the "environ" array. This makes it impossible for "environ" to be dropped by the linker. Therefore also drop the other logic to handle non-present "environ". Also add a testcase to validate the initialization of environ. Signed-off-by: Thomas Weißschuh Signed-off-by: Willy Tarreau --- tools/include/nolibc/stdlib.h | 12 ++---------- tools/testing/selftests/nolibc/nolibc-test.c | 7 ++++--- 2 files changed, 6 insertions(+), 13 deletions(-) (limited to 'tools/testing') diff --git a/tools/include/nolibc/stdlib.h b/tools/include/nolibc/stdlib.h index 902162f80337..bacfd35c5156 100644 --- a/tools/include/nolibc/stdlib.h +++ b/tools/include/nolibc/stdlib.h @@ -83,11 +83,10 @@ void free(void *ptr) * declared as a char **, and must be terminated by a NULL (it is recommended * to set this variable to the "envp" argument of main()). If the requested * environment variable exists its value is returned otherwise NULL is - * returned. getenv() is forcefully inlined so that the reference to "environ" - * will be dropped if unused, even at -O0. + * returned. */ static __attribute__((unused)) -char *_getenv(const char *name, char **environ) +char *getenv(const char *name) { int idx, i; @@ -102,13 +101,6 @@ char *_getenv(const char *name, char **environ) return NULL; } -static __inline__ __attribute__((unused,always_inline)) -char *getenv(const char *name) -{ - extern char **environ; - return _getenv(name, environ); -} - static __attribute__((unused)) unsigned long getauxval(unsigned long type) { diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index 6c94e491e2f8..8682e6f1e7a4 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -44,8 +44,8 @@ #define SINT_MAX_OF_TYPE(type) (((type)1 << (sizeof(type) * 8 - 2)) - (type)1 + ((type)1 << (sizeof(type) * 8 - 2))) #define SINT_MIN_OF_TYPE(type) (-SINT_MAX_OF_TYPE(type) - 1) -/* will be used by nolibc by getenv() */ -char **environ; +/* will be used to test initialization of environ */ +static char **test_envp; /* will be used by some test cases as readable file, please don't write it */ static const char *argv0; @@ -787,6 +787,7 @@ int run_stdlib(int min, int max) * test numbers. */ switch (test + __LINE__ + 1) { + CASE_TEST(environ); EXPECT_PTREQ(1, environ, test_envp); break; CASE_TEST(getenv_TERM); EXPECT_STRNZ(1, getenv("TERM")); break; CASE_TEST(getenv_blah); EXPECT_STRZR(1, getenv("blah")); break; CASE_TEST(setcmp_blah_blah); EXPECT_EQ(1, strcmp("blah", "blah"), 0); break; @@ -1120,7 +1121,7 @@ int main(int argc, char **argv, char **envp) char *test; argv0 = argv[0]; - environ = envp; + test_envp = envp; /* when called as init, it's possible that no console was opened, for * example if no /dev file system was provided. We'll check that fd#1 -- cgit v1.2.3 From 3097783ecf3b963a6b700f32b6190b0910e39724 Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Tue, 11 Jul 2023 11:48:39 +0200 Subject: selftests/nolibc: make evaluation of test conditions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If "cond" is a multi-token statement the behavior of the preprocessor will lead to the negation "!" to be only applied to the first token. Although currently no test uses such multi-token conditions but it can happen at any time. Put braces around "cond" to ensure the negation works as expected. Signed-off-by: Thomas Weißschuh Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 42 ++++++++++++++-------------- 1 file changed, 21 insertions(+), 21 deletions(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index 8682e6f1e7a4..54b8421fe54a 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -147,7 +147,7 @@ static int pad_spc(int llen, int cnt, const char *fmt, ...) */ #define EXPECT_ZR(cond, expr) \ - do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_zr(expr, llen); } while (0) + do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_zr(expr, llen); } while (0) static int expect_zr(int expr, int llen) { @@ -160,7 +160,7 @@ static int expect_zr(int expr, int llen) #define EXPECT_NZ(cond, expr, val) \ - do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_nz(expr, llen; } while (0) + do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_nz(expr, llen; } while (0) static int expect_nz(int expr, int llen) { @@ -173,7 +173,7 @@ static int expect_nz(int expr, int llen) #define EXPECT_EQ(cond, expr, val) \ - do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_eq(expr, llen, val); } while (0) + do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_eq(expr, llen, val); } while (0) static int expect_eq(uint64_t expr, int llen, uint64_t val) { @@ -186,7 +186,7 @@ static int expect_eq(uint64_t expr, int llen, uint64_t val) #define EXPECT_NE(cond, expr, val) \ - do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ne(expr, llen, val); } while (0) + do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ne(expr, llen, val); } while (0) static int expect_ne(int expr, int llen, int val) { @@ -199,7 +199,7 @@ static int expect_ne(int expr, int llen, int val) #define EXPECT_GE(cond, expr, val) \ - do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ge(expr, llen, val); } while (0) + do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ge(expr, llen, val); } while (0) static int expect_ge(int expr, int llen, int val) { @@ -212,7 +212,7 @@ static int expect_ge(int expr, int llen, int val) #define EXPECT_GT(cond, expr, val) \ - do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_gt(expr, llen, val); } while (0) + do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_gt(expr, llen, val); } while (0) static int expect_gt(int expr, int llen, int val) { @@ -225,7 +225,7 @@ static int expect_gt(int expr, int llen, int val) #define EXPECT_LE(cond, expr, val) \ - do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_le(expr, llen, val); } while (0) + do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_le(expr, llen, val); } while (0) static int expect_le(int expr, int llen, int val) { @@ -238,7 +238,7 @@ static int expect_le(int expr, int llen, int val) #define EXPECT_LT(cond, expr, val) \ - do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_lt(expr, llen, val); } while (0) + do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_lt(expr, llen, val); } while (0) static int expect_lt(int expr, int llen, int val) { @@ -251,7 +251,7 @@ static int expect_lt(int expr, int llen, int val) #define EXPECT_SYSZR(cond, expr) \ - do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_syszr(expr, llen); } while (0) + do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_syszr(expr, llen); } while (0) static int expect_syszr(int expr, int llen) { @@ -270,7 +270,7 @@ static int expect_syszr(int expr, int llen) #define EXPECT_SYSEQ(cond, expr, val) \ - do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_syseq(expr, llen, val); } while (0) + do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_syseq(expr, llen, val); } while (0) static int expect_syseq(int expr, int llen, int val) { @@ -289,7 +289,7 @@ static int expect_syseq(int expr, int llen, int val) #define EXPECT_SYSNE(cond, expr, val) \ - do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_sysne(expr, llen, val); } while (0) + do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_sysne(expr, llen, val); } while (0) static int expect_sysne(int expr, int llen, int val) { @@ -308,7 +308,7 @@ static int expect_sysne(int expr, int llen, int val) #define EXPECT_SYSER2(cond, expr, expret, experr1, experr2) \ - do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_syserr2(expr, expret, experr1, experr2, llen); } while (0) + do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_syserr2(expr, expret, experr1, experr2, llen); } while (0) #define EXPECT_SYSER(cond, expr, expret, experr) \ EXPECT_SYSER2(cond, expr, expret, experr, 0) @@ -334,7 +334,7 @@ static int expect_syserr2(int expr, int expret, int experr1, int experr2, int ll #define EXPECT_PTRZR(cond, expr) \ - do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ptrzr(expr, llen); } while (0) + do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ptrzr(expr, llen); } while (0) static int expect_ptrzr(const void *expr, int llen) { @@ -352,7 +352,7 @@ static int expect_ptrzr(const void *expr, int llen) #define EXPECT_PTRNZ(cond, expr) \ - do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ptrnz(expr, llen); } while (0) + do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ptrnz(expr, llen); } while (0) static int expect_ptrnz(const void *expr, int llen) { @@ -369,7 +369,7 @@ static int expect_ptrnz(const void *expr, int llen) } #define EXPECT_PTREQ(cond, expr, cmp) \ - do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ptreq(expr, llen, cmp); } while (0) + do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ptreq(expr, llen, cmp); } while (0) static int expect_ptreq(const void *expr, int llen, const void *cmp) { @@ -386,7 +386,7 @@ static int expect_ptreq(const void *expr, int llen, const void *cmp) } #define EXPECT_PTRNE(cond, expr, cmp) \ - do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ptrne(expr, llen, cmp); } while (0) + do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ptrne(expr, llen, cmp); } while (0) static int expect_ptrne(const void *expr, int llen, const void *cmp) { @@ -403,7 +403,7 @@ static int expect_ptrne(const void *expr, int llen, const void *cmp) } #define EXPECT_PTRER2(cond, expr, expret, experr1, experr2) \ - do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ptrerr2(expr, expret, experr1, experr2, llen); } while (0) + do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ptrerr2(expr, expret, experr1, experr2, llen); } while (0) #define EXPECT_PTRER(cond, expr, expret, experr) \ EXPECT_PTRER2(cond, expr, expret, experr, 0) @@ -428,7 +428,7 @@ static int expect_ptrerr2(const void *expr, const void *expret, int experr1, int } #define EXPECT_STRZR(cond, expr) \ - do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_strzr(expr, llen); } while (0) + do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_strzr(expr, llen); } while (0) static int expect_strzr(const char *expr, int llen) { @@ -446,7 +446,7 @@ static int expect_strzr(const char *expr, int llen) #define EXPECT_STRNZ(cond, expr) \ - do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_strnz(expr, llen); } while (0) + do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_strnz(expr, llen); } while (0) static int expect_strnz(const char *expr, int llen) { @@ -464,7 +464,7 @@ static int expect_strnz(const char *expr, int llen) #define EXPECT_STREQ(cond, expr, cmp) \ - do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_streq(expr, llen, cmp); } while (0) + do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_streq(expr, llen, cmp); } while (0) static int expect_streq(const char *expr, int llen, const char *cmp) { @@ -482,7 +482,7 @@ static int expect_streq(const char *expr, int llen, const char *cmp) #define EXPECT_STRNE(cond, expr, cmp) \ - do { if (!cond) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_strne(expr, llen, cmp); } while (0) + do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_strne(expr, llen, cmp); } while (0) static int expect_strne(const char *expr, int llen, const char *cmp) { -- cgit v1.2.3 From b184a261e526ada6207b62a96624cc97d741565c Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Tue, 11 Jul 2023 11:48:40 +0200 Subject: selftests/nolibc: simplify status printing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pad_spc() is only ever used to print the status message of testcases. The line size is always constant, the return value is never used and the format string is never used as such. Remove all the unneeded logic and simplify the API and its users. Signed-off-by: Thomas Weißschuh Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 154 ++++++++++++++------------- 1 file changed, 81 insertions(+), 73 deletions(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index 54b8421fe54a..644490d93070 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -127,17 +127,25 @@ static void putcharn(char c, size_t n) fputs(buf, stdout); } -static int pad_spc(int llen, int cnt, const char *fmt, ...) +enum RESULT { + OK, + FAIL, + SKIPPED, +}; + +static void result(int llen, enum RESULT r) { - va_list args; - int ret; + const char *msg; - putcharn(' ', cnt - llen); + if (r == OK) + msg = " [OK]"; + else if (r == SKIPPED) + msg = "[SKIPPED]"; + else + msg = "[FAIL]"; - va_start(args, fmt); - ret = vfprintf(stdout, fmt, args); - va_end(args); - return ret < 0 ? ret : ret + cnt - llen; + putcharn(' ', 64 - llen); + puts(msg); } /* The tests below are intended to be used by the macroes, which evaluate @@ -147,111 +155,111 @@ static int pad_spc(int llen, int cnt, const char *fmt, ...) */ #define EXPECT_ZR(cond, expr) \ - do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_zr(expr, llen); } while (0) + do { if (!(cond)) result(llen, SKIPPED); else ret += expect_zr(expr, llen); } while (0) static int expect_zr(int expr, int llen) { int ret = !(expr == 0); llen += printf(" = %d ", expr); - pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n"); + result(llen, ret ? FAIL : OK); return ret; } #define EXPECT_NZ(cond, expr, val) \ - do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_nz(expr, llen; } while (0) + do { if (!(cond)) result(llen, SKIPPED); else ret += expect_nz(expr, llen; } while (0) static int expect_nz(int expr, int llen) { int ret = !(expr != 0); llen += printf(" = %d ", expr); - pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n"); + result(llen, ret ? FAIL : OK); return ret; } #define EXPECT_EQ(cond, expr, val) \ - do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_eq(expr, llen, val); } while (0) + do { if (!(cond)) result(llen, SKIPPED); else ret += expect_eq(expr, llen, val); } while (0) static int expect_eq(uint64_t expr, int llen, uint64_t val) { int ret = !(expr == val); llen += printf(" = %lld ", (long long)expr); - pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n"); + result(llen, ret ? FAIL : OK); return ret; } #define EXPECT_NE(cond, expr, val) \ - do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ne(expr, llen, val); } while (0) + do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ne(expr, llen, val); } while (0) static int expect_ne(int expr, int llen, int val) { int ret = !(expr != val); llen += printf(" = %d ", expr); - pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n"); + result(llen, ret ? FAIL : OK); return ret; } #define EXPECT_GE(cond, expr, val) \ - do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ge(expr, llen, val); } while (0) + do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ge(expr, llen, val); } while (0) static int expect_ge(int expr, int llen, int val) { int ret = !(expr >= val); llen += printf(" = %d ", expr); - pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n"); + result(llen, ret ? FAIL : OK); return ret; } #define EXPECT_GT(cond, expr, val) \ - do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_gt(expr, llen, val); } while (0) + do { if (!(cond)) result(llen, SKIPPED); else ret += expect_gt(expr, llen, val); } while (0) static int expect_gt(int expr, int llen, int val) { int ret = !(expr > val); llen += printf(" = %d ", expr); - pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n"); + result(llen, ret ? FAIL : OK); return ret; } #define EXPECT_LE(cond, expr, val) \ - do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_le(expr, llen, val); } while (0) + do { if (!(cond)) result(llen, SKIPPED); else ret += expect_le(expr, llen, val); } while (0) static int expect_le(int expr, int llen, int val) { int ret = !(expr <= val); llen += printf(" = %d ", expr); - pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n"); + result(llen, ret ? FAIL : OK); return ret; } #define EXPECT_LT(cond, expr, val) \ - do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_lt(expr, llen, val); } while (0) + do { if (!(cond)) result(llen, SKIPPED); else ret += expect_lt(expr, llen, val); } while (0) static int expect_lt(int expr, int llen, int val) { int ret = !(expr < val); llen += printf(" = %d ", expr); - pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n"); + result(llen, ret ? FAIL : OK); return ret; } #define EXPECT_SYSZR(cond, expr) \ - do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_syszr(expr, llen); } while (0) + do { if (!(cond)) result(llen, SKIPPED); else ret += expect_syszr(expr, llen); } while (0) static int expect_syszr(int expr, int llen) { @@ -260,17 +268,17 @@ static int expect_syszr(int expr, int llen) if (expr) { ret = 1; llen += printf(" = %d %s ", expr, errorname(errno)); - llen += pad_spc(llen, 64, "[FAIL]\n"); + result(llen, FAIL); } else { llen += printf(" = %d ", expr); - llen += pad_spc(llen, 64, " [OK]\n"); + result(llen, OK); } return ret; } #define EXPECT_SYSEQ(cond, expr, val) \ - do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_syseq(expr, llen, val); } while (0) + do { if (!(cond)) result(llen, SKIPPED); else ret += expect_syseq(expr, llen, val); } while (0) static int expect_syseq(int expr, int llen, int val) { @@ -279,17 +287,17 @@ static int expect_syseq(int expr, int llen, int val) if (expr != val) { ret = 1; llen += printf(" = %d %s ", expr, errorname(errno)); - llen += pad_spc(llen, 64, "[FAIL]\n"); + result(llen, FAIL); } else { llen += printf(" = %d ", expr); - llen += pad_spc(llen, 64, " [OK]\n"); + result(llen, OK); } return ret; } #define EXPECT_SYSNE(cond, expr, val) \ - do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_sysne(expr, llen, val); } while (0) + do { if (!(cond)) result(llen, SKIPPED); else ret += expect_sysne(expr, llen, val); } while (0) static int expect_sysne(int expr, int llen, int val) { @@ -298,17 +306,17 @@ static int expect_sysne(int expr, int llen, int val) if (expr == val) { ret = 1; llen += printf(" = %d %s ", expr, errorname(errno)); - llen += pad_spc(llen, 64, "[FAIL]\n"); + result(llen, FAIL); } else { llen += printf(" = %d ", expr); - llen += pad_spc(llen, 64, " [OK]\n"); + result(llen, OK); } return ret; } #define EXPECT_SYSER2(cond, expr, expret, experr1, experr2) \ - do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_syserr2(expr, expret, experr1, experr2, llen); } while (0) + do { if (!(cond)) result(llen, SKIPPED); else ret += expect_syserr2(expr, expret, experr1, experr2, llen); } while (0) #define EXPECT_SYSER(cond, expr, expret, experr) \ EXPECT_SYSER2(cond, expr, expret, experr, 0) @@ -325,16 +333,16 @@ static int expect_syserr2(int expr, int expret, int experr1, int experr2, int ll llen += printf(" != (%d %s) ", expret, errorname(experr1)); else llen += printf(" != (%d %s %s) ", expret, errorname(experr1), errorname(experr2)); - llen += pad_spc(llen, 64, "[FAIL]\n"); + result(llen, FAIL); } else { - llen += pad_spc(llen, 64, " [OK]\n"); + result(llen, OK); } return ret; } #define EXPECT_PTRZR(cond, expr) \ - do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ptrzr(expr, llen); } while (0) + do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ptrzr(expr, llen); } while (0) static int expect_ptrzr(const void *expr, int llen) { @@ -343,16 +351,16 @@ static int expect_ptrzr(const void *expr, int llen) llen += printf(" = <%p> ", expr); if (expr) { ret = 1; - llen += pad_spc(llen, 64, "[FAIL]\n"); + result(llen, FAIL); } else { - llen += pad_spc(llen, 64, " [OK]\n"); + result(llen, OK); } return ret; } #define EXPECT_PTRNZ(cond, expr) \ - do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ptrnz(expr, llen); } while (0) + do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ptrnz(expr, llen); } while (0) static int expect_ptrnz(const void *expr, int llen) { @@ -361,15 +369,15 @@ static int expect_ptrnz(const void *expr, int llen) llen += printf(" = <%p> ", expr); if (!expr) { ret = 1; - llen += pad_spc(llen, 64, "[FAIL]\n"); + result(llen, FAIL); } else { - llen += pad_spc(llen, 64, " [OK]\n"); + result(llen, OK); } return ret; } #define EXPECT_PTREQ(cond, expr, cmp) \ - do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ptreq(expr, llen, cmp); } while (0) + do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ptreq(expr, llen, cmp); } while (0) static int expect_ptreq(const void *expr, int llen, const void *cmp) { @@ -378,15 +386,15 @@ static int expect_ptreq(const void *expr, int llen, const void *cmp) llen += printf(" = <%p> ", expr); if (expr != cmp) { ret = 1; - llen += pad_spc(llen, 64, "[FAIL]\n"); + result(llen, FAIL); } else { - llen += pad_spc(llen, 64, " [OK]\n"); + result(llen, OK); } return ret; } #define EXPECT_PTRNE(cond, expr, cmp) \ - do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ptrne(expr, llen, cmp); } while (0) + do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ptrne(expr, llen, cmp); } while (0) static int expect_ptrne(const void *expr, int llen, const void *cmp) { @@ -395,15 +403,15 @@ static int expect_ptrne(const void *expr, int llen, const void *cmp) llen += printf(" = <%p> ", expr); if (expr == cmp) { ret = 1; - llen += pad_spc(llen, 64, "[FAIL]\n"); + result(llen, FAIL); } else { - llen += pad_spc(llen, 64, " [OK]\n"); + result(llen, OK); } return ret; } #define EXPECT_PTRER2(cond, expr, expret, experr1, experr2) \ - do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_ptrerr2(expr, expret, experr1, experr2, llen); } while (0) + do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ptrerr2(expr, expret, experr1, experr2, llen); } while (0) #define EXPECT_PTRER(cond, expr, expret, experr) \ EXPECT_PTRER2(cond, expr, expret, experr, 0) @@ -420,15 +428,15 @@ static int expect_ptrerr2(const void *expr, const void *expret, int experr1, int llen += printf(" != (<%p> %s) ", expret, errorname(experr1)); else llen += printf(" != (<%p> %s %s) ", expret, errorname(experr1), errorname(experr2)); - llen += pad_spc(llen, 64, "[FAIL]\n"); + result(llen, FAIL); } else { - llen += pad_spc(llen, 64, " [OK]\n"); + result(llen, OK); } return ret; } #define EXPECT_STRZR(cond, expr) \ - do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_strzr(expr, llen); } while (0) + do { if (!(cond)) result(llen, SKIPPED); else ret += expect_strzr(expr, llen); } while (0) static int expect_strzr(const char *expr, int llen) { @@ -437,16 +445,16 @@ static int expect_strzr(const char *expr, int llen) llen += printf(" = <%s> ", expr); if (expr) { ret = 1; - llen += pad_spc(llen, 64, "[FAIL]\n"); + result(llen, FAIL); } else { - llen += pad_spc(llen, 64, " [OK]\n"); + result(llen, OK); } return ret; } #define EXPECT_STRNZ(cond, expr) \ - do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_strnz(expr, llen); } while (0) + do { if (!(cond)) result(llen, SKIPPED); else ret += expect_strnz(expr, llen); } while (0) static int expect_strnz(const char *expr, int llen) { @@ -455,16 +463,16 @@ static int expect_strnz(const char *expr, int llen) llen += printf(" = <%s> ", expr); if (!expr) { ret = 1; - llen += pad_spc(llen, 64, "[FAIL]\n"); + result(llen, FAIL); } else { - llen += pad_spc(llen, 64, " [OK]\n"); + result(llen, OK); } return ret; } #define EXPECT_STREQ(cond, expr, cmp) \ - do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_streq(expr, llen, cmp); } while (0) + do { if (!(cond)) result(llen, SKIPPED); else ret += expect_streq(expr, llen, cmp); } while (0) static int expect_streq(const char *expr, int llen, const char *cmp) { @@ -473,16 +481,16 @@ static int expect_streq(const char *expr, int llen, const char *cmp) llen += printf(" = <%s> ", expr); if (strcmp(expr, cmp) != 0) { ret = 1; - llen += pad_spc(llen, 64, "[FAIL]\n"); + result(llen, FAIL); } else { - llen += pad_spc(llen, 64, " [OK]\n"); + result(llen, OK); } return ret; } #define EXPECT_STRNE(cond, expr, cmp) \ - do { if (!(cond)) pad_spc(llen, 64, "[SKIPPED]\n"); else ret += expect_strne(expr, llen, cmp); } while (0) + do { if (!(cond)) result(llen, SKIPPED); else ret += expect_strne(expr, llen, cmp); } while (0) static int expect_strne(const char *expr, int llen, const char *cmp) { @@ -491,9 +499,9 @@ static int expect_strne(const char *expr, int llen, const char *cmp) llen += printf(" = <%s> ", expr); if (strcmp(expr, cmp) == 0) { ret = 1; - llen += pad_spc(llen, 64, "[FAIL]\n"); + result(llen, FAIL); } else { - llen += pad_spc(llen, 64, " [OK]\n"); + result(llen, OK); } return ret; } @@ -880,13 +888,13 @@ static int expect_vfprintf(int llen, size_t c, const char *expected, const char fd = open("/tmp", O_TMPFILE | O_EXCL | O_RDWR, 0600); if (fd == -1) { - pad_spc(llen, 64, "[SKIPPED]\n"); + result(llen, SKIPPED); return 0; } memfile = fdopen(fd, "w+"); if (!memfile) { - pad_spc(llen, 64, "[FAIL]\n"); + result(llen, FAIL); return 1; } @@ -896,7 +904,7 @@ static int expect_vfprintf(int llen, size_t c, const char *expected, const char if (w != c) { llen += printf(" written(%d) != %d", w, (int) c); - pad_spc(llen, 64, "[FAIL]\n"); + result(llen, FAIL); return 1; } @@ -910,14 +918,14 @@ static int expect_vfprintf(int llen, size_t c, const char *expected, const char if (r != w) { llen += printf(" written(%d) != read(%d)", w, r); - pad_spc(llen, 64, "[FAIL]\n"); + result(llen, FAIL); return 1; } llen += printf(" \"%s\" = \"%s\"", expected, buf); ret = strncmp(expected, buf, c); - pad_spc(llen, 64, ret ? "[FAIL]\n" : " [OK]\n"); + result(llen, ret ? FAIL : OK); return ret; } @@ -973,14 +981,14 @@ static int run_protection(int min, int max) #if !defined(_NOLIBC_STACKPROTECTOR) llen += printf("not supported"); - pad_spc(llen, 64, "[SKIPPED]\n"); + result(llen, SKIPPED); return 0; #endif #if defined(_NOLIBC_STACKPROTECTOR) if (!__stack_chk_guard) { llen += printf("__stack_chk_guard not initialized"); - pad_spc(llen, 64, "[FAIL]\n"); + result(llen, FAIL); return 1; } #endif @@ -991,7 +999,7 @@ static int run_protection(int min, int max) switch (pid) { case -1: llen += printf("fork()"); - pad_spc(llen, 64, "[FAIL]\n"); + result(llen, FAIL); return 1; case 0: @@ -1007,10 +1015,10 @@ static int run_protection(int min, int max) if (pid == -1 || !WIFSIGNALED(status) || WTERMSIG(status) != SIGABRT) { llen += printf("waitpid()"); - pad_spc(llen, 64, "[FAIL]\n"); + result(llen, FAIL); return 1; } - pad_spc(llen, 64, " [OK]\n"); + result(llen, OK); return 0; } } -- cgit v1.2.3 From ceb528feb7c89c9ef1e25e00494db9c6866cd4c3 Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Tue, 11 Jul 2023 11:48:42 +0200 Subject: selftests/nolibc: avoid gaps in test numbers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As the test numbers are based on line numbers gaps without testcases are to be avoided. Instead use the already existing test condition logic to implement conditional execution. Signed-off-by: Thomas Weißschuh Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 30 ++++++++++++---------------- 1 file changed, 13 insertions(+), 17 deletions(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index 644490d93070..7cd1aa800b8a 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -851,23 +851,19 @@ int run_stdlib(int min, int max) CASE_TEST(limit_int_fast64_min); EXPECT_EQ(1, INT_FAST64_MIN, (int_fast64_t) INT64_MIN); break; CASE_TEST(limit_int_fast64_max); EXPECT_EQ(1, INT_FAST64_MAX, (int_fast64_t) INT64_MAX); break; CASE_TEST(limit_uint_fast64_max); EXPECT_EQ(1, UINT_FAST64_MAX, (uint_fast64_t) UINT64_MAX); break; -#if __SIZEOF_LONG__ == 8 - CASE_TEST(limit_intptr_min); EXPECT_EQ(1, INTPTR_MIN, (intptr_t) 0x8000000000000000LL); break; - CASE_TEST(limit_intptr_max); EXPECT_EQ(1, INTPTR_MAX, (intptr_t) 0x7fffffffffffffffLL); break; - CASE_TEST(limit_uintptr_max); EXPECT_EQ(1, UINTPTR_MAX, (uintptr_t) 0xffffffffffffffffULL); break; - CASE_TEST(limit_ptrdiff_min); EXPECT_EQ(1, PTRDIFF_MIN, (ptrdiff_t) 0x8000000000000000LL); break; - CASE_TEST(limit_ptrdiff_max); EXPECT_EQ(1, PTRDIFF_MAX, (ptrdiff_t) 0x7fffffffffffffffLL); break; - CASE_TEST(limit_size_max); EXPECT_EQ(1, SIZE_MAX, (size_t) 0xffffffffffffffffULL); break; -#elif __SIZEOF_LONG__ == 4 - CASE_TEST(limit_intptr_min); EXPECT_EQ(1, INTPTR_MIN, (intptr_t) 0x80000000); break; - CASE_TEST(limit_intptr_max); EXPECT_EQ(1, INTPTR_MAX, (intptr_t) 0x7fffffff); break; - CASE_TEST(limit_uintptr_max); EXPECT_EQ(1, UINTPTR_MAX, (uintptr_t) 0xffffffffU); break; - CASE_TEST(limit_ptrdiff_min); EXPECT_EQ(1, PTRDIFF_MIN, (ptrdiff_t) 0x80000000); break; - CASE_TEST(limit_ptrdiff_max); EXPECT_EQ(1, PTRDIFF_MAX, (ptrdiff_t) 0x7fffffff); break; - CASE_TEST(limit_size_max); EXPECT_EQ(1, SIZE_MAX, (size_t) 0xffffffffU); break; -#else -# warning "__SIZEOF_LONG__ is undefined" -#endif /* __SIZEOF_LONG__ */ + CASE_TEST(sizeof_long_sane); EXPECT_EQ(1, sizeof(long) == 8 || sizeof(long) == 4, 1); break; + CASE_TEST(limit_intptr_min_64); EXPECT_EQ(sizeof(long) == 8, INTPTR_MIN, (intptr_t) 0x8000000000000000LL); break; + CASE_TEST(limit_intptr_max_64); EXPECT_EQ(sizeof(long) == 8, INTPTR_MAX, (intptr_t) 0x7fffffffffffffffLL); break; + CASE_TEST(limit_uintptr_max_64); EXPECT_EQ(sizeof(long) == 8, UINTPTR_MAX, (uintptr_t) 0xffffffffffffffffULL); break; + CASE_TEST(limit_ptrdiff_min_64); EXPECT_EQ(sizeof(long) == 8, PTRDIFF_MIN, (ptrdiff_t) 0x8000000000000000LL); break; + CASE_TEST(limit_ptrdiff_max_64); EXPECT_EQ(sizeof(long) == 8, PTRDIFF_MAX, (ptrdiff_t) 0x7fffffffffffffffLL); break; + CASE_TEST(limit_size_max_64); EXPECT_EQ(sizeof(long) == 8, SIZE_MAX, (size_t) 0xffffffffffffffffULL); break; + CASE_TEST(limit_intptr_min_32); EXPECT_EQ(sizeof(long) == 4, INTPTR_MIN, (intptr_t) 0x80000000); break; + CASE_TEST(limit_intptr_max_32); EXPECT_EQ(sizeof(long) == 4, INTPTR_MAX, (intptr_t) 0x7fffffff); break; + CASE_TEST(limit_uintptr_max_32); EXPECT_EQ(sizeof(long) == 4, UINTPTR_MAX, (uintptr_t) 0xffffffffU); break; + CASE_TEST(limit_ptrdiff_min_32); EXPECT_EQ(sizeof(long) == 4, PTRDIFF_MIN, (ptrdiff_t) 0x80000000); break; + CASE_TEST(limit_ptrdiff_max_32); EXPECT_EQ(sizeof(long) == 4, PTRDIFF_MAX, (ptrdiff_t) 0x7fffffff); break; + CASE_TEST(limit_size_max_32); EXPECT_EQ(sizeof(long) == 4, SIZE_MAX, (size_t) 0xffffffffU); break; case __LINE__: return ret; /* must be last */ /* note: do not set any defaults so as to permit holes above */ -- cgit v1.2.3 From fd3a9efde8db4b9e7738d1338c23ac43de723d5f Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Sun, 16 Jul 2023 02:33:26 +0800 Subject: selftests/nolibc: add EXPECT_PTRGE, EXPECT_PTRGT, EXPECT_PTRLE, EXPECT_PTRLT 4 new pointer compare macros are added, they are similar to the integer compare macros. Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 50 ++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index 7cd1aa800b8a..b3a66c3ffaf5 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -410,6 +410,56 @@ static int expect_ptrne(const void *expr, int llen, const void *cmp) return ret; } +#define EXPECT_PTRGE(cond, expr, cmp) \ + do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ptrge(expr, llen, cmp); } while (0) + +static int expect_ptrge(const void *expr, int llen, const void *cmp) +{ + int ret = !(expr >= cmp); + + llen += printf(" = <%p> ", expr); + result(llen, ret ? FAIL : OK); + return ret; +} + +#define EXPECT_PTRGT(cond, expr, cmp) \ + do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ptrgt(expr, llen, cmp); } while (0) + +static int expect_ptrgt(const void *expr, int llen, const void *cmp) +{ + int ret = !(expr > cmp); + + llen += printf(" = <%p> ", expr); + result(llen, ret ? FAIL : OK); + return ret; +} + + +#define EXPECT_PTRLE(cond, expr, cmp) \ + do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ptrle(expr, llen, cmp); } while (0) + +static int expect_ptrle(const void *expr, int llen, const void *cmp) +{ + int ret = !(expr <= cmp); + + llen += printf(" = <%p> ", expr); + result(llen, ret ? FAIL : OK); + return ret; +} + + +#define EXPECT_PTRLT(cond, expr, cmp) \ + do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ptrlt(expr, llen, cmp); } while (0) + +static int expect_ptrlt(const void *expr, int llen, const void *cmp) +{ + int ret = !(expr < cmp); + + llen += printf(" = <%p> ", expr); + result(llen, ret ? FAIL : OK); + return ret; +} + #define EXPECT_PTRER2(cond, expr, expret, experr1, experr2) \ do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ptrerr2(expr, expret, experr1, experr2, llen); } while (0) -- cgit v1.2.3 From 48967b73f8fe7e64e1d292e963dd45daff4ffa60 Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Sun, 16 Jul 2023 02:34:32 +0800 Subject: selftests/nolibc: add testcases for startup code The startup code is critical to get the right argc, argv, envp/environ and _auxv, let's add a startup test group and the corresponding testcases. The "environ" test case is also moved from the stdlib test group to this new startup test group and it is renamed to "environ_envp". Since argv0 has been used by many other test cases, let's add testcases to gurantee it too. Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 56 +++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index b3a66c3ffaf5..737205702e3d 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -15,6 +15,7 @@ #include #ifndef _NOLIBC_STDIO_H /* standard libcs need more includes */ +#include #include #include #include @@ -47,6 +48,12 @@ /* will be used to test initialization of environ */ static char **test_envp; +/* will be used to test initialization of argv */ +static char **test_argv; + +/* will be used to test initialization of argc */ +static int test_argc; + /* will be used by some test cases as readable file, please don't write it */ static const char *argv0; @@ -561,6 +568,51 @@ static int expect_strne(const char *expr, int llen, const char *cmp) #define CASE_TEST(name) \ case __LINE__: llen += printf("%d %s", test, #name); +int run_startup(int min, int max) +{ + int test; + int ret = 0; + /* kernel at least passes HOME and TERM, shell passes more */ + int env_total = 2; + /* checking NULL for argv/argv0, environ and _auxv is not enough, let's compare with sbrk(0) or &end */ + extern char end; + char *brk = sbrk(0) != (void *)-1 ? sbrk(0) : &end; + /* differ from nolibc, both glibc and musl have no global _auxv */ + const unsigned long *test_auxv = (void *)-1; +#ifdef NOLIBC + test_auxv = _auxv; +#endif + + for (test = min; test >= 0 && test <= max; test++) { + int llen = 0; /* line length */ + + /* avoid leaving empty lines below, this will insert holes into + * test numbers. + */ + switch (test + __LINE__ + 1) { + CASE_TEST(argc); EXPECT_GE(1, test_argc, 1); break; + CASE_TEST(argv_addr); EXPECT_PTRGT(1, test_argv, brk); break; + CASE_TEST(argv_environ); EXPECT_PTRLT(1, test_argv, environ); break; + CASE_TEST(argv_total); EXPECT_EQ(1, environ - test_argv - 1, test_argc ?: 1); break; + CASE_TEST(argv0_addr); EXPECT_PTRGT(1, argv0, brk); break; + CASE_TEST(argv0_str); EXPECT_STRNZ(1, argv0 > brk ? argv0 : NULL); break; + CASE_TEST(argv0_len); EXPECT_GE(1, argv0 > brk ? strlen(argv0) : 0, 1); break; + CASE_TEST(environ_addr); EXPECT_PTRGT(1, environ, brk); break; + CASE_TEST(environ_envp); EXPECT_PTREQ(1, environ, test_envp); break; + CASE_TEST(environ_auxv); EXPECT_PTRLT(test_auxv != (void *)-1, environ, test_auxv); break; + CASE_TEST(environ_total); EXPECT_GE(test_auxv != (void *)-1, (void *)test_auxv - (void *)environ - 1, env_total); break; + CASE_TEST(environ_HOME); EXPECT_PTRNZ(1, getenv("HOME")); break; + CASE_TEST(auxv_addr); EXPECT_PTRGT(test_auxv != (void *)-1, test_auxv, brk); break; + CASE_TEST(auxv_AT_UID); EXPECT_EQ(1, getauxval(AT_UID), getuid()); break; + CASE_TEST(auxv_AT_PAGESZ); EXPECT_GE(1, getauxval(AT_PAGESZ), 4096); break; + case __LINE__: + return ret; /* must be last */ + /* note: do not set any defaults so as to permit holes above */ + } + } + return ret; +} + /* used by some syscall tests below */ int test_getdents64(const char *dir) @@ -845,7 +897,6 @@ int run_stdlib(int min, int max) * test numbers. */ switch (test + __LINE__ + 1) { - CASE_TEST(environ); EXPECT_PTREQ(1, environ, test_envp); break; CASE_TEST(getenv_TERM); EXPECT_STRNZ(1, getenv("TERM")); break; CASE_TEST(getenv_blah); EXPECT_STRZR(1, getenv("blah")); break; CASE_TEST(setcmp_blah_blah); EXPECT_EQ(1, strcmp("blah", "blah"), 0); break; @@ -1129,6 +1180,7 @@ int prepare(void) /* This is the definition of known test names, with their functions */ static const struct test test_names[] = { /* add new tests here */ + { .name = "startup", .func = run_startup }, { .name = "syscall", .func = run_syscall }, { .name = "stdlib", .func = run_stdlib }, { .name = "vfprintf", .func = run_vfprintf }, @@ -1175,6 +1227,8 @@ int main(int argc, char **argv, char **envp) char *test; argv0 = argv[0]; + test_argc = argc; + test_argv = argv; test_envp = envp; /* when called as init, it's possible that no console was opened, for -- cgit v1.2.3 From b81434073b7a113f37f2a2b69c6c28605d4ffb6f Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Sun, 16 Jul 2023 02:35:39 +0800 Subject: selftests/nolibc: allow run nolibc-test locally It is able to run nolibc-test directly without qemu-user when the target machine is the same as the host machine. Sometimes, the result running locally may help a lot when the qemu-user package is too old. When the target machine differs from the host machine, it is also able to run nolibc-test directly with qemu-user-static + binfmt_misc. Link: https://lore.kernel.org/lkml/ZKutZwIOfy5MqedG@1wt.eu/ Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/Makefile | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/Makefile b/tools/testing/selftests/nolibc/Makefile index d31d6cea82e2..b42e67b1a7e2 100644 --- a/tools/testing/selftests/nolibc/Makefile +++ b/tools/testing/selftests/nolibc/Makefile @@ -133,10 +133,16 @@ nolibc-test: nolibc-test.c sysroot/$(ARCH)/include libc-test: nolibc-test.c $(QUIET_CC)$(CC) -o $@ $< +# local libc-test run-libc-test: libc-test $(Q)./libc-test > "$(CURDIR)/run.out" || : $(Q)$(REPORT) $(CURDIR)/run.out +# local nolibc-test +run-nolibc-test: nolibc-test + $(Q)./nolibc-test > "$(CURDIR)/run.out" || : + $(Q)$(REPORT) $(CURDIR)/run.out + # qemu user-land test run-user: nolibc-test $(Q)qemu-$(QEMU_ARCH) ./nolibc-test > "$(CURDIR)/run.out" || : -- cgit v1.2.3 From 850fad7de8277d3ad1009c766d0edfdd67e744eb Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Sun, 16 Jul 2023 02:36:46 +0800 Subject: selftests/nolibc: allow test -include /path/to/nolibc.h As the head comment of nolibc-test.c shows, it can be built in 3 ways: $(CC) -nostdlib -include /path/to/nolibc.h => NOLIBC already defined $(CC) -nostdlib -I/path/to/nolibc/sysroot => _NOLIBC_* guards are present $(CC) with default libc => NOLIBC* never defined Only last two of them are tested currently, let's allow test the first one too. This may help to find issues about using nolibc.h to build programs. it derives from this change: commit 3a8039e289a3 ("tools/nolibc: Fix build of stdio.h due to header ordering") Usage: // test with sysroot by default $ make run-user // test without sysroot, using nolibc.h directly $ make run-user NOLIBC_SYSROOT=0 Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/Makefile | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/Makefile b/tools/testing/selftests/nolibc/Makefile index b42e67b1a7e2..f42adef87e12 100644 --- a/tools/testing/selftests/nolibc/Makefile +++ b/tools/testing/selftests/nolibc/Makefile @@ -126,9 +126,15 @@ sysroot/$(ARCH)/include: $(Q)$(MAKE) -C ../../../include/nolibc ARCH=$(ARCH) OUTPUT=$(CURDIR)/sysroot/ headers_standalone $(Q)mv sysroot/sysroot sysroot/$(ARCH) +ifneq ($(NOLIBC_SYSROOT),0) nolibc-test: nolibc-test.c sysroot/$(ARCH)/include $(QUIET_CC)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ \ -nostdlib -static -Isysroot/$(ARCH)/include $< -lgcc +else +nolibc-test: nolibc-test.c + $(QUIET_CC)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ \ + -nostdlib -static -include ../../../include/nolibc/nolibc.h $< -lgcc +endif libc-test: nolibc-test.c $(QUIET_CC)$(CC) -o $@ $< -- cgit v1.2.3 From 447e56023fc281c588e4977add552f4d49d78b22 Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Wed, 26 Jul 2023 08:08:13 +0200 Subject: selftests/nolibc: avoid buffer underrun in space printing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the test description is longer than the status alignment the parameter 'n' to putcharn() would lead to a signed underflow that then gets converted to a very large unsigned value. This in turn leads out-of-bound writes in memset() crashing the application. The failure case of EXPECT_PTRER() used in "mmap_bad" exhibits this exact behavior. Fixes: 29f5540be392 ("selftests/nolibc: add EXPECT_PTREQ, EXPECT_PTRNE and EXPECT_PTRER") Signed-off-by: Thomas Weißschuh Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index 737205702e3d..3f5a256631ca 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -151,7 +151,8 @@ static void result(int llen, enum RESULT r) else msg = "[FAIL]"; - putcharn(' ', 64 - llen); + if (llen < 64) + putcharn(' ', 64 - llen); puts(msg); } -- cgit v1.2.3 From e7d0129df681aa23bb6528f44186accc38d655f0 Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Wed, 26 Jul 2023 00:43:36 +0800 Subject: selftests/nolibc: mmap_munmap_good: fix up return value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The other tests use 1 as failure, mmap_munmap_good uses -1 as failure, let's fix up this. Signed-off-by: Zhangjin Wu Reviewed-by: Thomas Weißschuh Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index 3f5a256631ca..4d39823a567e 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -726,7 +726,7 @@ int test_mmap_munmap(void) page_size = getpagesize(); if (page_size < 0) - return -1; + return 1; /* find a right file to mmap, existed and accessible */ for (i = 0; files[i] != NULL; i++) { @@ -737,7 +737,7 @@ int test_mmap_munmap(void) break; } if (ret == -1) - return ret; + return 1; ret = stat(files[i], &stat_buf); if (ret == -1) @@ -757,7 +757,7 @@ int test_mmap_munmap(void) mem = mmap(NULL, length + offset - pa_offset, PROT_READ, MAP_SHARED, fd, pa_offset); if (mem == MAP_FAILED) { - ret = -1; + ret = 1; goto end; } @@ -765,7 +765,7 @@ int test_mmap_munmap(void) end: close(fd); - return ret; + return !!ret; } -- cgit v1.2.3 From 5c01259b1256ebc59bf6d64b396e7464f21c2583 Mon Sep 17 00:00:00 2001 From: Yuan Tan Date: Tue, 1 Aug 2023 23:40:23 +0800 Subject: selftests/nolibc: add testcase for pipe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a test case of pipe that sends and receives message in a single process. Suggested-by: Thomas Weißschuh Suggested-by: Willy Tarreau Link: https://lore.kernel.org/all/c5de2d13-3752-4e1b-90d9-f58cca99c702@t-8ch.de/ Signed-off-by: Yuan Tan Reviewed-by: Thomas Weißschuh [wt: fixed the "len" type to size_t to address a sign-compare warning with upcoming patches] Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index 4d39823a567e..7952107a2db8 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -768,6 +768,27 @@ end: return !!ret; } +static int test_pipe(void) +{ + const char *const msg = "hello, nolibc"; + int pipefd[2]; + char buf[32]; + size_t len; + + if (pipe(pipefd) == -1) + return 1; + + write(pipefd[1], msg, strlen(msg)); + close(pipefd[1]); + len = read(pipefd[0], buf, sizeof(buf)); + close(pipefd[0]); + + if (len != strlen(msg)) + return 1; + + return !!memcmp(buf, msg, len); +} + /* Run syscall tests between IDs and . * Return 0 on success, non-zero on failure. @@ -853,6 +874,7 @@ int run_syscall(int min, int max) CASE_TEST(mmap_munmap_good); EXPECT_SYSZR(1, test_mmap_munmap()); break; CASE_TEST(open_tty); EXPECT_SYSNE(1, tmp = open("/dev/null", 0), -1); if (tmp != -1) close(tmp); break; CASE_TEST(open_blah); EXPECT_SYSER(1, tmp = open("/proc/self/blah", 0), -1, ENOENT); if (tmp != -1) close(tmp); break; + CASE_TEST(pipe); EXPECT_SYSZR(1, test_pipe()); break; CASE_TEST(poll_null); EXPECT_SYSZR(1, poll(NULL, 0, 0)); break; CASE_TEST(poll_stdout); EXPECT_SYSNE(1, ({ struct pollfd fds = { 1, POLLOUT, 0}; poll(&fds, 1, 0); }), -1); break; CASE_TEST(poll_fault); EXPECT_SYSER(1, poll((void *)1, 1, 0), -1, EFAULT); break; -- cgit v1.2.3 From 640775022572380b6f78247f10c036e69d404947 Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Thu, 3 Aug 2023 09:28:46 +0200 Subject: tools/nolibc: fix return type of getpagesize() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's documented as returning int which is also implemented by glibc and musl, so adopt that return type. Signed-off-by: Thomas Weißschuh Signed-off-by: Willy Tarreau --- tools/include/nolibc/sys.h | 4 ++-- tools/testing/selftests/nolibc/nolibc-test.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'tools/testing') diff --git a/tools/include/nolibc/sys.h b/tools/include/nolibc/sys.h index e12dd962c578..c151533ba8e9 100644 --- a/tools/include/nolibc/sys.h +++ b/tools/include/nolibc/sys.h @@ -460,11 +460,11 @@ pid_t gettid(void) static unsigned long getauxval(unsigned long key); /* - * long getpagesize(void); + * int getpagesize(void); */ static __attribute__((unused)) -long getpagesize(void) +int getpagesize(void) { return __sysret(getauxval(AT_PAGESZ) ?: -ENOENT); } diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index 7952107a2db8..31f2bd789e2d 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -636,7 +636,7 @@ int test_getdents64(const char *dir) static int test_getpagesize(void) { - long x = getpagesize(); + int x = getpagesize(); int c; if (x < 0) -- cgit v1.2.3 From ca283457b3c675e5ab6762a750b1b9c495864993 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 6 Aug 2023 12:58:52 +0200 Subject: selftests/nolibc: avoid warnings during intptr tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Recent fix ceb528feb7c8 ("selftests/nolibc: avoid gaps in test numbers") had the annoying side effect of always returning skipped tests, which are normally supposed to happen only when certain features are missing to run the test (missing kernel options, toolchain not supporting stack-protector etc). As such there are now always warnings. Let's modify the test to not use the condition and instead use a ternary expression to check the result. Fixes: ceb528feb7c8 ("selftests/nolibc: avoid gaps in test numbers") Cc: Thomas WeiÃ<9F>schuh Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index 31f2bd789e2d..c6b8d05f7f46 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -976,18 +976,13 @@ int run_stdlib(int min, int max) CASE_TEST(limit_int_fast64_max); EXPECT_EQ(1, INT_FAST64_MAX, (int_fast64_t) INT64_MAX); break; CASE_TEST(limit_uint_fast64_max); EXPECT_EQ(1, UINT_FAST64_MAX, (uint_fast64_t) UINT64_MAX); break; CASE_TEST(sizeof_long_sane); EXPECT_EQ(1, sizeof(long) == 8 || sizeof(long) == 4, 1); break; - CASE_TEST(limit_intptr_min_64); EXPECT_EQ(sizeof(long) == 8, INTPTR_MIN, (intptr_t) 0x8000000000000000LL); break; - CASE_TEST(limit_intptr_max_64); EXPECT_EQ(sizeof(long) == 8, INTPTR_MAX, (intptr_t) 0x7fffffffffffffffLL); break; - CASE_TEST(limit_uintptr_max_64); EXPECT_EQ(sizeof(long) == 8, UINTPTR_MAX, (uintptr_t) 0xffffffffffffffffULL); break; - CASE_TEST(limit_ptrdiff_min_64); EXPECT_EQ(sizeof(long) == 8, PTRDIFF_MIN, (ptrdiff_t) 0x8000000000000000LL); break; - CASE_TEST(limit_ptrdiff_max_64); EXPECT_EQ(sizeof(long) == 8, PTRDIFF_MAX, (ptrdiff_t) 0x7fffffffffffffffLL); break; - CASE_TEST(limit_size_max_64); EXPECT_EQ(sizeof(long) == 8, SIZE_MAX, (size_t) 0xffffffffffffffffULL); break; - CASE_TEST(limit_intptr_min_32); EXPECT_EQ(sizeof(long) == 4, INTPTR_MIN, (intptr_t) 0x80000000); break; - CASE_TEST(limit_intptr_max_32); EXPECT_EQ(sizeof(long) == 4, INTPTR_MAX, (intptr_t) 0x7fffffff); break; - CASE_TEST(limit_uintptr_max_32); EXPECT_EQ(sizeof(long) == 4, UINTPTR_MAX, (uintptr_t) 0xffffffffU); break; - CASE_TEST(limit_ptrdiff_min_32); EXPECT_EQ(sizeof(long) == 4, PTRDIFF_MIN, (ptrdiff_t) 0x80000000); break; - CASE_TEST(limit_ptrdiff_max_32); EXPECT_EQ(sizeof(long) == 4, PTRDIFF_MAX, (ptrdiff_t) 0x7fffffff); break; - CASE_TEST(limit_size_max_32); EXPECT_EQ(sizeof(long) == 4, SIZE_MAX, (size_t) 0xffffffffU); break; + CASE_TEST(limit_intptr_min); EXPECT_EQ(1, INTPTR_MIN, sizeof(long) == 8 ? (intptr_t) 0x8000000000000000LL : (intptr_t) 0x80000000); break; + CASE_TEST(limit_intptr_max); EXPECT_EQ(1, INTPTR_MAX, sizeof(long) == 8 ? (intptr_t) 0x7fffffffffffffffLL : (intptr_t) 0x7fffffff); break; + CASE_TEST(limit_uintptr_max); EXPECT_EQ(1, UINTPTR_MAX, sizeof(long) == 8 ? (uintptr_t) 0xffffffffffffffffULL : (uintptr_t) 0xffffffffU); break; + CASE_TEST(limit_ptrdiff_min); EXPECT_EQ(1, PTRDIFF_MIN, sizeof(long) == 8 ? (ptrdiff_t) 0x8000000000000000LL : (ptrdiff_t) 0x80000000); break; + CASE_TEST(limit_ptrdiff_max); EXPECT_EQ(1, PTRDIFF_MAX, sizeof(long) == 8 ? (ptrdiff_t) 0x7fffffffffffffffLL : (ptrdiff_t) 0x7fffffff); break; + CASE_TEST(limit_size_max); EXPECT_EQ(1, SIZE_MAX, sizeof(long) == 8 ? (size_t) 0xffffffffffffffffULL : (size_t) 0xffffffffU); break; + case __LINE__: return ret; /* must be last */ /* note: do not set any defaults so as to permit holes above */ -- cgit v1.2.3 From 79df81aaea1158ad57878b4e5f341dc2618bdaac Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Thu, 3 Aug 2023 09:28:50 +0200 Subject: selftests/nolibc: drop unused variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These got copied around as new testcases where created. Signed-off-by: Thomas Weißschuh Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index c6b8d05f7f46..fce04fde0a2d 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -909,9 +909,7 @@ int run_syscall(int min, int max) int run_stdlib(int min, int max) { int test; - int tmp; int ret = 0; - void *p1, *p2; for (test = min; test >= 0 && test <= max; test++) { int llen = 0; /* line length */ @@ -1047,9 +1045,7 @@ static int expect_vfprintf(int llen, size_t c, const char *expected, const char static int run_vfprintf(int min, int max) { int test; - int tmp; int ret = 0; - void *p1, *p2; for (test = min; test >= 0 && test <= max; test++) { int llen = 0; /* line length */ -- cgit v1.2.3 From 10874f20ee8752b04cac22f2a711394c7060b913 Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Thu, 3 Aug 2023 09:28:51 +0200 Subject: selftests/nolibc: mark test helpers as potentially unused MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When warning about unused functions these would be reported by we want to keep them for future use. Suggested-by: Zhangjin Wu Link: https://lore.kernel.org/lkml/20230731064826.16584-1-falcon@tinylab.org/ Suggested-by: Willy Tarreau Link: https://lore.kernel.org/lkml/20230731224929.GA18296@1wt.eu/ Signed-off-by: Thomas Weißschuh Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 75 ++++++++++++++++++---------- 1 file changed, 50 insertions(+), 25 deletions(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index fce04fde0a2d..b7d1a996626b 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -165,7 +165,8 @@ static void result(int llen, enum RESULT r) #define EXPECT_ZR(cond, expr) \ do { if (!(cond)) result(llen, SKIPPED); else ret += expect_zr(expr, llen); } while (0) -static int expect_zr(int expr, int llen) +static __attribute__((unused)) +int expect_zr(int expr, int llen) { int ret = !(expr == 0); @@ -178,7 +179,8 @@ static int expect_zr(int expr, int llen) #define EXPECT_NZ(cond, expr, val) \ do { if (!(cond)) result(llen, SKIPPED); else ret += expect_nz(expr, llen; } while (0) -static int expect_nz(int expr, int llen) +static __attribute__((unused)) +int expect_nz(int expr, int llen) { int ret = !(expr != 0); @@ -191,7 +193,8 @@ static int expect_nz(int expr, int llen) #define EXPECT_EQ(cond, expr, val) \ do { if (!(cond)) result(llen, SKIPPED); else ret += expect_eq(expr, llen, val); } while (0) -static int expect_eq(uint64_t expr, int llen, uint64_t val) +static __attribute__((unused)) +int expect_eq(uint64_t expr, int llen, uint64_t val) { int ret = !(expr == val); @@ -204,7 +207,8 @@ static int expect_eq(uint64_t expr, int llen, uint64_t val) #define EXPECT_NE(cond, expr, val) \ do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ne(expr, llen, val); } while (0) -static int expect_ne(int expr, int llen, int val) +static __attribute__((unused)) +int expect_ne(int expr, int llen, int val) { int ret = !(expr != val); @@ -217,7 +221,8 @@ static int expect_ne(int expr, int llen, int val) #define EXPECT_GE(cond, expr, val) \ do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ge(expr, llen, val); } while (0) -static int expect_ge(int expr, int llen, int val) +static __attribute__((unused)) +int expect_ge(int expr, int llen, int val) { int ret = !(expr >= val); @@ -230,7 +235,8 @@ static int expect_ge(int expr, int llen, int val) #define EXPECT_GT(cond, expr, val) \ do { if (!(cond)) result(llen, SKIPPED); else ret += expect_gt(expr, llen, val); } while (0) -static int expect_gt(int expr, int llen, int val) +static __attribute__((unused)) +int expect_gt(int expr, int llen, int val) { int ret = !(expr > val); @@ -243,7 +249,8 @@ static int expect_gt(int expr, int llen, int val) #define EXPECT_LE(cond, expr, val) \ do { if (!(cond)) result(llen, SKIPPED); else ret += expect_le(expr, llen, val); } while (0) -static int expect_le(int expr, int llen, int val) +static __attribute__((unused)) +int expect_le(int expr, int llen, int val) { int ret = !(expr <= val); @@ -256,7 +263,8 @@ static int expect_le(int expr, int llen, int val) #define EXPECT_LT(cond, expr, val) \ do { if (!(cond)) result(llen, SKIPPED); else ret += expect_lt(expr, llen, val); } while (0) -static int expect_lt(int expr, int llen, int val) +static __attribute__((unused)) +int expect_lt(int expr, int llen, int val) { int ret = !(expr < val); @@ -269,7 +277,8 @@ static int expect_lt(int expr, int llen, int val) #define EXPECT_SYSZR(cond, expr) \ do { if (!(cond)) result(llen, SKIPPED); else ret += expect_syszr(expr, llen); } while (0) -static int expect_syszr(int expr, int llen) +static __attribute__((unused)) +int expect_syszr(int expr, int llen) { int ret = 0; @@ -288,7 +297,8 @@ static int expect_syszr(int expr, int llen) #define EXPECT_SYSEQ(cond, expr, val) \ do { if (!(cond)) result(llen, SKIPPED); else ret += expect_syseq(expr, llen, val); } while (0) -static int expect_syseq(int expr, int llen, int val) +static __attribute__((unused)) +int expect_syseq(int expr, int llen, int val) { int ret = 0; @@ -307,7 +317,8 @@ static int expect_syseq(int expr, int llen, int val) #define EXPECT_SYSNE(cond, expr, val) \ do { if (!(cond)) result(llen, SKIPPED); else ret += expect_sysne(expr, llen, val); } while (0) -static int expect_sysne(int expr, int llen, int val) +static __attribute__((unused)) +int expect_sysne(int expr, int llen, int val) { int ret = 0; @@ -329,7 +340,8 @@ static int expect_sysne(int expr, int llen, int val) #define EXPECT_SYSER(cond, expr, expret, experr) \ EXPECT_SYSER2(cond, expr, expret, experr, 0) -static int expect_syserr2(int expr, int expret, int experr1, int experr2, int llen) +static __attribute__((unused)) +int expect_syserr2(int expr, int expret, int experr1, int experr2, int llen) { int ret = 0; int _errno = errno; @@ -352,7 +364,8 @@ static int expect_syserr2(int expr, int expret, int experr1, int experr2, int ll #define EXPECT_PTRZR(cond, expr) \ do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ptrzr(expr, llen); } while (0) -static int expect_ptrzr(const void *expr, int llen) +static __attribute__((unused)) +int expect_ptrzr(const void *expr, int llen) { int ret = 0; @@ -370,7 +383,8 @@ static int expect_ptrzr(const void *expr, int llen) #define EXPECT_PTRNZ(cond, expr) \ do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ptrnz(expr, llen); } while (0) -static int expect_ptrnz(const void *expr, int llen) +static __attribute__((unused)) +int expect_ptrnz(const void *expr, int llen) { int ret = 0; @@ -387,7 +401,8 @@ static int expect_ptrnz(const void *expr, int llen) #define EXPECT_PTREQ(cond, expr, cmp) \ do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ptreq(expr, llen, cmp); } while (0) -static int expect_ptreq(const void *expr, int llen, const void *cmp) +static __attribute__((unused)) +int expect_ptreq(const void *expr, int llen, const void *cmp) { int ret = 0; @@ -404,7 +419,8 @@ static int expect_ptreq(const void *expr, int llen, const void *cmp) #define EXPECT_PTRNE(cond, expr, cmp) \ do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ptrne(expr, llen, cmp); } while (0) -static int expect_ptrne(const void *expr, int llen, const void *cmp) +static __attribute__((unused)) +int expect_ptrne(const void *expr, int llen, const void *cmp) { int ret = 0; @@ -421,7 +437,8 @@ static int expect_ptrne(const void *expr, int llen, const void *cmp) #define EXPECT_PTRGE(cond, expr, cmp) \ do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ptrge(expr, llen, cmp); } while (0) -static int expect_ptrge(const void *expr, int llen, const void *cmp) +static __attribute__((unused)) +int expect_ptrge(const void *expr, int llen, const void *cmp) { int ret = !(expr >= cmp); @@ -433,7 +450,8 @@ static int expect_ptrge(const void *expr, int llen, const void *cmp) #define EXPECT_PTRGT(cond, expr, cmp) \ do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ptrgt(expr, llen, cmp); } while (0) -static int expect_ptrgt(const void *expr, int llen, const void *cmp) +static __attribute__((unused)) +int expect_ptrgt(const void *expr, int llen, const void *cmp) { int ret = !(expr > cmp); @@ -446,7 +464,8 @@ static int expect_ptrgt(const void *expr, int llen, const void *cmp) #define EXPECT_PTRLE(cond, expr, cmp) \ do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ptrle(expr, llen, cmp); } while (0) -static int expect_ptrle(const void *expr, int llen, const void *cmp) +static __attribute__((unused)) +int expect_ptrle(const void *expr, int llen, const void *cmp) { int ret = !(expr <= cmp); @@ -459,7 +478,8 @@ static int expect_ptrle(const void *expr, int llen, const void *cmp) #define EXPECT_PTRLT(cond, expr, cmp) \ do { if (!(cond)) result(llen, SKIPPED); else ret += expect_ptrlt(expr, llen, cmp); } while (0) -static int expect_ptrlt(const void *expr, int llen, const void *cmp) +static __attribute__((unused)) +int expect_ptrlt(const void *expr, int llen, const void *cmp) { int ret = !(expr < cmp); @@ -474,7 +494,8 @@ static int expect_ptrlt(const void *expr, int llen, const void *cmp) #define EXPECT_PTRER(cond, expr, expret, experr) \ EXPECT_PTRER2(cond, expr, expret, experr, 0) -static int expect_ptrerr2(const void *expr, const void *expret, int experr1, int experr2, int llen) +static __attribute__((unused)) +int expect_ptrerr2(const void *expr, const void *expret, int experr1, int experr2, int llen) { int ret = 0; int _errno = errno; @@ -496,7 +517,8 @@ static int expect_ptrerr2(const void *expr, const void *expret, int experr1, int #define EXPECT_STRZR(cond, expr) \ do { if (!(cond)) result(llen, SKIPPED); else ret += expect_strzr(expr, llen); } while (0) -static int expect_strzr(const char *expr, int llen) +static __attribute__((unused)) +int expect_strzr(const char *expr, int llen) { int ret = 0; @@ -514,7 +536,8 @@ static int expect_strzr(const char *expr, int llen) #define EXPECT_STRNZ(cond, expr) \ do { if (!(cond)) result(llen, SKIPPED); else ret += expect_strnz(expr, llen); } while (0) -static int expect_strnz(const char *expr, int llen) +static __attribute__((unused)) +int expect_strnz(const char *expr, int llen) { int ret = 0; @@ -532,7 +555,8 @@ static int expect_strnz(const char *expr, int llen) #define EXPECT_STREQ(cond, expr, cmp) \ do { if (!(cond)) result(llen, SKIPPED); else ret += expect_streq(expr, llen, cmp); } while (0) -static int expect_streq(const char *expr, int llen, const char *cmp) +static __attribute__((unused)) +int expect_streq(const char *expr, int llen, const char *cmp) { int ret = 0; @@ -550,7 +574,8 @@ static int expect_streq(const char *expr, int llen, const char *cmp) #define EXPECT_STRNE(cond, expr, cmp) \ do { if (!(cond)) result(llen, SKIPPED); else ret += expect_strne(expr, llen, cmp); } while (0) -static int expect_strne(const char *expr, int llen, const char *cmp) +static __attribute__((unused)) +int expect_strne(const char *expr, int llen, const char *cmp) { int ret = 0; -- cgit v1.2.3 From 17e66f235e4ab43423741dcb946a4d140d8ba34b Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Thu, 3 Aug 2023 09:28:52 +0200 Subject: selftests/nolibc: make functions static if possible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows the compiler to generate warnings if they go unused. Functions that are supposed to be used as breakpoints should not be static, so un-statify those if necessary. Signed-off-by: Thomas Weißschuh Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index b7d1a996626b..da9926e6ec82 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -80,7 +80,7 @@ char *itoa(int i) /* returns the error name (e.g. "ENOENT") for common errors, "SUCCESS" for 0, * or the decimal value for less common ones. */ -const char *errorname(int err) +static const char *errorname(int err) { switch (err) { case 0: return "SUCCESS"; @@ -659,7 +659,7 @@ int test_getdents64(const char *dir) return ret; } -static int test_getpagesize(void) +int test_getpagesize(void) { int x = getpagesize(); int c; @@ -688,7 +688,7 @@ static int test_getpagesize(void) return !c; } -static int test_fork(void) +int test_fork(void) { int status; pid_t pid; @@ -713,7 +713,7 @@ static int test_fork(void) } } -static int test_stat_timestamps(void) +int test_stat_timestamps(void) { struct stat st; @@ -793,7 +793,7 @@ end: return !!ret; } -static int test_pipe(void) +int test_pipe(void) { const char *const msg = "hello, nolibc"; int pipefd[2]; @@ -1227,7 +1227,7 @@ static const struct test test_names[] = { { 0 } }; -int is_setting_valid(char *test) +static int is_setting_valid(char *test) { int idx, len, test_len, valid = 0; char delimiter; -- cgit v1.2.3 From c8d078153fd8407073b714c6d4d6c9b95d5aa4e0 Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Thu, 3 Aug 2023 09:28:53 +0200 Subject: selftests/nolibc: avoid unused parameter warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This warning will be enabled later so avoid triggering it. Signed-off-by: Thomas Weißschuh Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index da9926e6ec82..9372abcac4c3 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -1108,7 +1108,8 @@ static int smash_stack(void) return 1; } -static int run_protection(int min, int max) +static int run_protection(int min __attribute__((unused)), + int max __attribute__((unused))) { pid_t pid; int llen = 0, status; -- cgit v1.2.3 From 711f91fdec714d6307f1fa044fb74d0a742b1494 Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Thu, 3 Aug 2023 09:28:54 +0200 Subject: selftests/nolibc: avoid sign-compare warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These warnings will be enabled later so avoid triggering them. Signed-off-by: Thomas Weißschuh Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index 9372abcac4c3..c2646707ccc2 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -737,9 +737,9 @@ int test_stat_timestamps(void) int test_mmap_munmap(void) { - int ret, fd, i; + int ret, fd, i, page_size; void *mem; - size_t page_size, file_size, length; + size_t file_size, length; off_t offset, pa_offset; struct stat stat_buf; const char * const files[] = { @@ -1017,7 +1017,7 @@ int run_stdlib(int min, int max) #define EXPECT_VFPRINTF(c, expected, fmt, ...) \ ret += expect_vfprintf(llen, c, expected, fmt, ##__VA_ARGS__) -static int expect_vfprintf(int llen, size_t c, const char *expected, const char *fmt, ...) +static int expect_vfprintf(int llen, int c, const char *expected, const char *fmt, ...) { int ret, fd, w, r; char buf[100]; @@ -1041,7 +1041,7 @@ static int expect_vfprintf(int llen, size_t c, const char *expected, const char va_end(args); if (w != c) { - llen += printf(" written(%d) != %d", w, (int) c); + llen += printf(" written(%d) != %d", w, c); result(llen, FAIL); return 1; } -- cgit v1.2.3 From 37266a9ec7f5a3144c2070baeea2628c30ef07e5 Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Thu, 3 Aug 2023 09:28:55 +0200 Subject: selftests/nolibc: use correct return type for read() and write() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid truncating values before comparing them. As printf in nolibc doesn't support ssize_t add casts to int for printing. Signed-off-by: Thomas Weißschuh Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index c2646707ccc2..23a5e4c57083 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -1019,7 +1019,8 @@ int run_stdlib(int min, int max) static int expect_vfprintf(int llen, int c, const char *expected, const char *fmt, ...) { - int ret, fd, w, r; + int ret, fd; + ssize_t w, r; char buf[100]; FILE *memfile; va_list args; @@ -1041,7 +1042,7 @@ static int expect_vfprintf(int llen, int c, const char *expected, const char *fm va_end(args); if (w != c) { - llen += printf(" written(%d) != %d", w, c); + llen += printf(" written(%d) != %d", (int)w, c); result(llen, FAIL); return 1; } @@ -1055,7 +1056,7 @@ static int expect_vfprintf(int llen, int c, const char *expected, const char *fm fclose(memfile); if (r != w) { - llen += printf(" written(%d) != read(%d)", w, r); + llen += printf(" written(%d) != read(%d)", (int)w, (int)r); result(llen, FAIL); return 1; } -- cgit v1.2.3 From 9c5e490093e83e165022e0311bd7df5aa06cc860 Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Thu, 3 Aug 2023 09:28:56 +0200 Subject: selftests/nolibc: prevent out of bounds access in expect_vfprintf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If read() fails and returns -1 (or returns garbage for some other reason) buf would be accessed out of bounds. Only use the return value of read() after it has been validated. Signed-off-by: Thomas Weißschuh Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/nolibc-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index 23a5e4c57083..e2b70641a1e7 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -1051,7 +1051,6 @@ static int expect_vfprintf(int llen, int c, const char *expected, const char *fm lseek(fd, 0, SEEK_SET); r = read(fd, buf, sizeof(buf) - 1); - buf[r] = '\0'; fclose(memfile); @@ -1061,6 +1060,7 @@ static int expect_vfprintf(int llen, int c, const char *expected, const char *fm return 1; } + buf[r] = '\0'; llen += printf(" \"%s\" = \"%s\"", expected, buf); ret = strncmp(expected, buf, c); -- cgit v1.2.3 From 711edef8f7cfa57f07cd336d77970a2b182bf9fc Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Thu, 3 Aug 2023 09:28:57 +0200 Subject: selftests/nolibc: don't strip nolibc-test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Binary size is not important for nolibc-test and some debugging information is nice to have, so don't strip the binary during linking. Signed-off-by: Thomas Weißschuh Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/Makefile b/tools/testing/selftests/nolibc/Makefile index f42adef87e12..b82d29b6c37f 100644 --- a/tools/testing/selftests/nolibc/Makefile +++ b/tools/testing/selftests/nolibc/Makefile @@ -82,7 +82,7 @@ CFLAGS_STACKPROTECTOR ?= $(call cc-option,-mstack-protector-guard=global $(call CFLAGS ?= -Os -fno-ident -fno-asynchronous-unwind-tables -std=c89 \ $(call cc-option,-fno-stack-protector) \ $(CFLAGS_$(ARCH)) $(CFLAGS_STACKPROTECTOR) -LDFLAGS := -s +LDFLAGS := REPORT ?= awk '/\[OK\][\r]*$$/{p++} /\[FAIL\][\r]*$$/{if (!f) printf("\n"); f++; print;} /\[SKIPPED\][\r]*$$/{s++} \ END{ printf("\n%3d test(s): %3d passed, %3d skipped, %3d failed => status: ", p+s+f, p, s, f); \ -- cgit v1.2.3 From 45f65f8d04db6fa328ab8e0191a8b9462d4bad95 Mon Sep 17 00:00:00 2001 From: Thomas Weißschuh Date: Thu, 3 Aug 2023 09:28:58 +0200 Subject: selftests/nolibc: enable compiler warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It will help the developers to avoid cruft and detect some bugs. Signed-off-by: Thomas Weißschuh Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/Makefile b/tools/testing/selftests/nolibc/Makefile index b82d29b6c37f..e8d09cbee2ab 100644 --- a/tools/testing/selftests/nolibc/Makefile +++ b/tools/testing/selftests/nolibc/Makefile @@ -79,7 +79,7 @@ endif CFLAGS_s390 = -m64 CFLAGS_mips = -EL CFLAGS_STACKPROTECTOR ?= $(call cc-option,-mstack-protector-guard=global $(call cc-option,-fstack-protector-all)) -CFLAGS ?= -Os -fno-ident -fno-asynchronous-unwind-tables -std=c89 \ +CFLAGS ?= -Os -fno-ident -fno-asynchronous-unwind-tables -std=c89 -W -Wall -Wextra \ $(call cc-option,-fno-stack-protector) \ $(CFLAGS_$(ARCH)) $(CFLAGS_STACKPROTECTOR) LDFLAGS := -- cgit v1.2.3 From c6c3734fb6b1c438d5586748753fee52a135c078 Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Sun, 6 Aug 2023 02:41:37 +0800 Subject: selftests/nolibc: add XARCH and ARCH mapping support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most of the CPU architectures have different variants, but kernel usually only accepts parts of them via the ARCH variable, the others should be customized via kernel config files. To simplify testing, a new XARCH variable is added to extend the kernel's ARCH with a few variants of the same architecture, and it is used to customize variant specific variables, at last XARCH is converted to the kernel's ARCH: e.g. make run XARCH= | \ | `-> variant specific variables: | IMAGE, DEFCONFIG, QEMU_ARCH, QEMU_ARGS, CFLAGS ... \ `---> kernel's ARCH XARCH and ARCH are carefully mapped to allow users to pass architecture variants via XARCH or pass architecture via ARCH from cmdline. PowerPC is the first user and also a very good reference architecture of this mapping, it has variants with different combinations of 32-bit/64-bit and bit endian/little endian. To use this mapping, the other architectures can refer to PowerPC, If the target architecture only has one variant, XARCH is simply an alias of ARCH, no additional mapping required. Suggested-by: Willy Tarreau Link: https://lore.kernel.org/lkml/20230702171715.GD16233@1wt.eu/ Link: https://lore.kernel.org/lkml/20230730061801.GA7690@1wt.eu/ Reviewed-by: Thomas Weißschuh Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/Makefile | 46 ++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 12 deletions(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/Makefile b/tools/testing/selftests/nolibc/Makefile index e8d09cbee2ab..09f3cead3853 100644 --- a/tools/testing/selftests/nolibc/Makefile +++ b/tools/testing/selftests/nolibc/Makefile @@ -14,6 +14,27 @@ include $(srctree)/scripts/subarch.include ARCH = $(SUBARCH) endif +# XARCH extends the kernel's ARCH with a few variants of the same +# architecture that only differ by the configuration, the toolchain +# and the Qemu program used. It is copied as-is into ARCH except for +# a few specific values which are mapped like this: +# +# XARCH | ARCH | config +# -------------|-----------|------------------------- +# ppc | powerpc | 32 bits +# ppc64 | powerpc | 64 bits big endian +# ppc64le | powerpc | 64 bits little endian +# +# It is recommended to only use XARCH, though it does not harm if +# ARCH is already set. For simplicity, ARCH is sufficient for all +# architectures where both are equal. + +# configure default variants for target kernel supported architectures +XARCH = $(or $(XARCH_$(ARCH)),$(ARCH)) + +# map from user input variants to their kernel supported architectures +ARCH := $(or $(ARCH_$(XARCH)),$(XARCH)) + # kernel image names by architecture IMAGE_i386 = arch/x86/boot/bzImage IMAGE_x86_64 = arch/x86/boot/bzImage @@ -24,7 +45,7 @@ IMAGE_mips = vmlinuz IMAGE_riscv = arch/riscv/boot/Image IMAGE_s390 = arch/s390/boot/bzImage IMAGE_loongarch = arch/loongarch/boot/vmlinuz.efi -IMAGE = $(IMAGE_$(ARCH)) +IMAGE = $(IMAGE_$(XARCH)) IMAGE_NAME = $(notdir $(IMAGE)) # default kernel configurations that appear to be usable @@ -37,7 +58,7 @@ DEFCONFIG_mips = malta_defconfig DEFCONFIG_riscv = defconfig DEFCONFIG_s390 = defconfig DEFCONFIG_loongarch = defconfig -DEFCONFIG = $(DEFCONFIG_$(ARCH)) +DEFCONFIG = $(DEFCONFIG_$(XARCH)) # optional tests to run (default = all) TEST = @@ -52,7 +73,7 @@ QEMU_ARCH_mips = mipsel # works with malta_defconfig QEMU_ARCH_riscv = riscv64 QEMU_ARCH_s390 = s390x QEMU_ARCH_loongarch = loongarch64 -QEMU_ARCH = $(QEMU_ARCH_$(ARCH)) +QEMU_ARCH = $(QEMU_ARCH_$(XARCH)) # QEMU_ARGS : some arch-specific args to pass to qemu QEMU_ARGS_i386 = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)" @@ -64,7 +85,7 @@ QEMU_ARGS_mips = -M malta -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" QEMU_ARGS_riscv = -M virt -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" QEMU_ARGS_s390 = -M s390-ccw-virtio -m 1G -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" QEMU_ARGS_loongarch = -M virt -append "console=ttyS0,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)" -QEMU_ARGS = $(QEMU_ARGS_$(ARCH)) $(QEMU_ARGS_EXTRA) +QEMU_ARGS = $(QEMU_ARGS_$(XARCH)) $(QEMU_ARGS_EXTRA) # OUTPUT is only set when run from the main makefile, otherwise # it defaults to this nolibc directory. @@ -81,7 +102,7 @@ CFLAGS_mips = -EL CFLAGS_STACKPROTECTOR ?= $(call cc-option,-mstack-protector-guard=global $(call cc-option,-fstack-protector-all)) CFLAGS ?= -Os -fno-ident -fno-asynchronous-unwind-tables -std=c89 -W -Wall -Wextra \ $(call cc-option,-fno-stack-protector) \ - $(CFLAGS_$(ARCH)) $(CFLAGS_STACKPROTECTOR) + $(CFLAGS_$(XARCH)) $(CFLAGS_STACKPROTECTOR) LDFLAGS := REPORT ?= awk '/\[OK\][\r]*$$/{p++} /\[FAIL\][\r]*$$/{if (!f) printf("\n"); f++; print;} /\[SKIPPED\][\r]*$$/{s++} \ @@ -96,24 +117,25 @@ help: @echo " sysroot create the nolibc sysroot here (uses \$$ARCH)" @echo " nolibc-test build the executable (uses \$$CC and \$$CROSS_COMPILE)" @echo " libc-test build an executable using the compiler's default libc instead" - @echo " run-user runs the executable under QEMU (uses \$$ARCH, \$$TEST)" + @echo " run-user runs the executable under QEMU (uses \$$XARCH, \$$TEST)" @echo " initramfs prepare the initramfs with nolibc-test" - @echo " defconfig create a fresh new default config (uses \$$ARCH)" - @echo " kernel (re)build the kernel with the initramfs (uses \$$ARCH)" - @echo " run runs the kernel in QEMU after building it (uses \$$ARCH, \$$TEST)" - @echo " rerun runs a previously prebuilt kernel in QEMU (uses \$$ARCH, \$$TEST)" + @echo " defconfig create a fresh new default config (uses \$$XARCH)" + @echo " kernel (re)build the kernel with the initramfs (uses \$$XARCH)" + @echo " run runs the kernel in QEMU after building it (uses \$$XARCH, \$$TEST)" + @echo " rerun runs a previously prebuilt kernel in QEMU (uses \$$XARCH, \$$TEST)" @echo " clean clean the sysroot, initramfs, build and output files" @echo "" @echo "The output file is \"run.out\". Test ranges may be passed using \$$TEST." @echo "" @echo "Currently using the following variables:" @echo " ARCH = $(ARCH)" + @echo " XARCH = $(XARCH)" @echo " CROSS_COMPILE = $(CROSS_COMPILE)" @echo " CC = $(CC)" @echo " OUTPUT = $(OUTPUT)" @echo " TEST = $(TEST)" - @echo " QEMU_ARCH = $(if $(QEMU_ARCH),$(QEMU_ARCH),UNKNOWN_ARCH) [determined from \$$ARCH]" - @echo " IMAGE_NAME = $(if $(IMAGE_NAME),$(IMAGE_NAME),UNKNOWN_ARCH) [determined from \$$ARCH]" + @echo " QEMU_ARCH = $(if $(QEMU_ARCH),$(QEMU_ARCH),UNKNOWN_ARCH) [determined from \$$XARCH]" + @echo " IMAGE_NAME = $(if $(IMAGE_NAME),$(IMAGE_NAME),UNKNOWN_ARCH) [determined from \$$XARCH]" @echo "" all: run -- cgit v1.2.3 From 587e98459102448d77c6d06aaca88aa99d3b8279 Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Sun, 6 Aug 2023 02:42:43 +0800 Subject: selftests/nolibc: add test support for ppc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Kernel uses ARCH=powerpc for both 32-bit and 64-bit PowerPC, here adds a ppc variant for 32-bit PowerPC and uses it as the default variant of powerpc architecture. Users can pass XARCH=ppc (or ARCH=powerpc) to test 32-bit PowerPC. The default qemu-system-ppc g3beige machine [1] is used to run 32-bit powerpc kernel with pmac32_defconfig. The missing PMACZILOG serial tty and console are enabled in another patch [2]. Note, - zImage doesn't boot due to "qemu-system-ppc: Some ROM regions are overlapping" error, so, vmlinux is used instead. - since the VSX support may be disabled in kernel side, to avoid "illegal instruction" errors due to missing VSX kernel support, let's simply let compiler not generate vector/scalar (VSX) instructions via the '-mno-vsx' option. - as 'man gcc' shows, '-mmultiple' is used to generate code that uses the load multiple word instructions and the store multiple word instructions. Those instructions do not work when the processor is in little-endian mode (except PPC740/PPC750), so, we only enable it for big endian powerpc. [1]: https://qemu.readthedocs.io/en/latest/system/ppc/powermac.html [2]: https://lore.kernel.org/lkml/bb7b5f9958b3e3a20f6573ff7ce7c5dc566e7e32.1690982937.git.tanyuan@tinylab.org/ Suggested-by: Willy Tarreau Link: https://lore.kernel.org/lkml/ZL9leVOI25S2+0+g@1wt.eu/ Reviewed-by: Thomas Weißschuh Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/Makefile | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/Makefile b/tools/testing/selftests/nolibc/Makefile index 09f3cead3853..2103fc79c4ef 100644 --- a/tools/testing/selftests/nolibc/Makefile +++ b/tools/testing/selftests/nolibc/Makefile @@ -30,9 +30,11 @@ endif # architectures where both are equal. # configure default variants for target kernel supported architectures +XARCH_powerpc = ppc XARCH = $(or $(XARCH_$(ARCH)),$(ARCH)) # map from user input variants to their kernel supported architectures +ARCH_ppc = powerpc ARCH := $(or $(ARCH_$(XARCH)),$(XARCH)) # kernel image names by architecture @@ -42,6 +44,7 @@ IMAGE_x86 = arch/x86/boot/bzImage IMAGE_arm64 = arch/arm64/boot/Image IMAGE_arm = arch/arm/boot/zImage IMAGE_mips = vmlinuz +IMAGE_ppc = vmlinux IMAGE_riscv = arch/riscv/boot/Image IMAGE_s390 = arch/s390/boot/bzImage IMAGE_loongarch = arch/loongarch/boot/vmlinuz.efi @@ -55,6 +58,7 @@ DEFCONFIG_x86 = defconfig DEFCONFIG_arm64 = defconfig DEFCONFIG_arm = multi_v7_defconfig DEFCONFIG_mips = malta_defconfig +DEFCONFIG_ppc = pmac32_defconfig DEFCONFIG_riscv = defconfig DEFCONFIG_s390 = defconfig DEFCONFIG_loongarch = defconfig @@ -70,6 +74,7 @@ QEMU_ARCH_x86 = x86_64 QEMU_ARCH_arm64 = aarch64 QEMU_ARCH_arm = arm QEMU_ARCH_mips = mipsel # works with malta_defconfig +QEMU_ARCH_ppc = ppc QEMU_ARCH_riscv = riscv64 QEMU_ARCH_s390 = s390x QEMU_ARCH_loongarch = loongarch64 @@ -82,6 +87,7 @@ QEMU_ARGS_x86 = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $( QEMU_ARGS_arm64 = -M virt -cpu cortex-a53 -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" QEMU_ARGS_arm = -M virt -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" QEMU_ARGS_mips = -M malta -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" +QEMU_ARGS_ppc = -M g3beige -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" QEMU_ARGS_riscv = -M virt -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" QEMU_ARGS_s390 = -M s390-ccw-virtio -m 1G -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" QEMU_ARGS_loongarch = -M virt -append "console=ttyS0,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)" @@ -97,6 +103,7 @@ else Q=@ endif +CFLAGS_ppc = -m32 -mbig-endian -mno-vsx $(call cc-option,-mmultiple) CFLAGS_s390 = -m64 CFLAGS_mips = -EL CFLAGS_STACKPROTECTOR ?= $(call cc-option,-mstack-protector-guard=global $(call cc-option,-fstack-protector-all)) -- cgit v1.2.3 From 8a5040cb3f5ac3b1bea5aaa1150daf43b883f938 Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Sun, 6 Aug 2023 02:43:53 +0800 Subject: selftests/nolibc: add test support for ppc64le MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Kernel uses ARCH=powerpc for both 32-bit and 64-bit PowerPC, here adds a ppc64le variant for little endian 64-bit PowerPC, users can pass XARCH=ppc64le to test it. The powernv machine of qemu-system-ppc64le is used for there is just a working powernv_defconfig. As the document [1] shows: PowerNV (as Non-Virtualized) is the “bare metal” platform using the OPAL firmware. It runs Linux on IBM and OpenPOWER systems and it can be used as an hypervisor OS, running KVM guests, or simply as a host OS. Notes, - since the VSX support may be disabled in kernel side, to avoid "illegal instruction" errors due to missing VSX kernel support, let's simply let compiler not generate vector/scalar (VSX) instructions via the '-mno-vsx' option. - little endian ppc64 prefers elfv2 to elfv1 if the toolchain (e.g. gcc 13.1.0) supports it, let's align with kernel, otherwise, our elfv1 binary will not run on kernel with elfv2 ABI. [1]: https://qemu.readthedocs.io/en/latest/system/ppc/powernv.html Suggested-by: Willy Tarreau Link: https://lore.kernel.org/lkml/20230722120747.GC17311@1wt.eu/ Reviewed-by: Thomas Weißschuh Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/Makefile | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/Makefile b/tools/testing/selftests/nolibc/Makefile index 2103fc79c4ef..a017b2048959 100644 --- a/tools/testing/selftests/nolibc/Makefile +++ b/tools/testing/selftests/nolibc/Makefile @@ -35,6 +35,7 @@ XARCH = $(or $(XARCH_$(ARCH)),$(ARCH)) # map from user input variants to their kernel supported architectures ARCH_ppc = powerpc +ARCH_ppc64le = powerpc ARCH := $(or $(ARCH_$(XARCH)),$(XARCH)) # kernel image names by architecture @@ -45,6 +46,7 @@ IMAGE_arm64 = arch/arm64/boot/Image IMAGE_arm = arch/arm/boot/zImage IMAGE_mips = vmlinuz IMAGE_ppc = vmlinux +IMAGE_ppc64le = arch/powerpc/boot/zImage IMAGE_riscv = arch/riscv/boot/Image IMAGE_s390 = arch/s390/boot/bzImage IMAGE_loongarch = arch/loongarch/boot/vmlinuz.efi @@ -59,6 +61,7 @@ DEFCONFIG_arm64 = defconfig DEFCONFIG_arm = multi_v7_defconfig DEFCONFIG_mips = malta_defconfig DEFCONFIG_ppc = pmac32_defconfig +DEFCONFIG_ppc64le = powernv_defconfig DEFCONFIG_riscv = defconfig DEFCONFIG_s390 = defconfig DEFCONFIG_loongarch = defconfig @@ -75,6 +78,7 @@ QEMU_ARCH_arm64 = aarch64 QEMU_ARCH_arm = arm QEMU_ARCH_mips = mipsel # works with malta_defconfig QEMU_ARCH_ppc = ppc +QEMU_ARCH_ppc64le = ppc64le QEMU_ARCH_riscv = riscv64 QEMU_ARCH_s390 = s390x QEMU_ARCH_loongarch = loongarch64 @@ -88,6 +92,7 @@ QEMU_ARGS_arm64 = -M virt -cpu cortex-a53 -append "panic=-1 $(TEST:%=NOLIBC QEMU_ARGS_arm = -M virt -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" QEMU_ARGS_mips = -M malta -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" QEMU_ARGS_ppc = -M g3beige -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" +QEMU_ARGS_ppc64le = -M powernv -append "console=hvc0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" QEMU_ARGS_riscv = -M virt -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" QEMU_ARGS_s390 = -M s390-ccw-virtio -m 1G -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" QEMU_ARGS_loongarch = -M virt -append "console=ttyS0,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)" @@ -104,6 +109,7 @@ Q=@ endif CFLAGS_ppc = -m32 -mbig-endian -mno-vsx $(call cc-option,-mmultiple) +CFLAGS_ppc64le = -m64 -mlittle-endian -mno-vsx $(call cc-option,-mabi=elfv2) CFLAGS_s390 = -m64 CFLAGS_mips = -EL CFLAGS_STACKPROTECTOR ?= $(call cc-option,-mstack-protector-guard=global $(call cc-option,-fstack-protector-all)) -- cgit v1.2.3 From faeb4e09fe77262f9a6b2f9f874eec0b6850721e Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Sun, 6 Aug 2023 02:44:58 +0800 Subject: selftests/nolibc: add test support for ppc64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Kernel uses ARCH=powerpc for both 32-bit and 64-bit PowerPC, here adds a ppc64 variant for big endian 64-bit PowerPC, users can pass XARCH=ppc64 to test it. The powernv machine of qemu-system-ppc64 is used with powernv_be_defconfig. As the document [1] shows: PowerNV (as Non-Virtualized) is the “bare metal” platform using the OPAL firmware. It runs Linux on IBM and OpenPOWER systems and it can be used as an hypervisor OS, running KVM guests, or simply as a host OS. Notes, - differs from little endian 64-bit PowerPC, vmlinux is used instead of zImage, because big endian zImage [2] only boot on qemu with x-vof=on (added from qemu v7.0) and a fixup patch [3] for qemu v7.0.51: - since the VSX support may be disabled in kernel side, to avoid "illegal instruction" errors due to missing VSX kernel support, let's simply let compiler not generate vector/scalar (VSX) instructions via the '-mno-vsx' option. - as 'man gcc' shows, '-mmultiple' is used to generate code that uses the load multiple word instructions and the store multiple word instructions. Those instructions do not work when the processor is in little-endian mode (except PPC740/PPC750), so, we only enable it for big endian powerpc. - for big endian ppc64, as the help message from arch/powerpc/Kconfig shows, the V2 ABI is standard for 64-bit little-endian, but for big-endian it is less well tested by kernel and toolchain, so, use elfv1 as-is, no need to explicitly ask toolchain to use elfv2 here. [1]: https://qemu.readthedocs.io/en/latest/system/ppc/powernv.html [2]: https://github.com/linuxppc/issues/issues/402 [3]: https://lore.kernel.org/qemu-devel/20220504065536.3534488-1-aik@ozlabs.ru/ Suggested-by: Willy Tarreau Link: https://lore.kernel.org/lkml/20230722121019.GD17311@1wt.eu/ Link: https://lore.kernel.org/lkml/20230719043353.GC5331@1wt.eu/ Reviewed-by: Thomas Weißschuh Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/Makefile | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/Makefile b/tools/testing/selftests/nolibc/Makefile index a017b2048959..f7eff081f41f 100644 --- a/tools/testing/selftests/nolibc/Makefile +++ b/tools/testing/selftests/nolibc/Makefile @@ -35,6 +35,7 @@ XARCH = $(or $(XARCH_$(ARCH)),$(ARCH)) # map from user input variants to their kernel supported architectures ARCH_ppc = powerpc +ARCH_ppc64 = powerpc ARCH_ppc64le = powerpc ARCH := $(or $(ARCH_$(XARCH)),$(XARCH)) @@ -46,6 +47,7 @@ IMAGE_arm64 = arch/arm64/boot/Image IMAGE_arm = arch/arm/boot/zImage IMAGE_mips = vmlinuz IMAGE_ppc = vmlinux +IMAGE_ppc64 = vmlinux IMAGE_ppc64le = arch/powerpc/boot/zImage IMAGE_riscv = arch/riscv/boot/Image IMAGE_s390 = arch/s390/boot/bzImage @@ -61,6 +63,7 @@ DEFCONFIG_arm64 = defconfig DEFCONFIG_arm = multi_v7_defconfig DEFCONFIG_mips = malta_defconfig DEFCONFIG_ppc = pmac32_defconfig +DEFCONFIG_ppc64 = powernv_be_defconfig DEFCONFIG_ppc64le = powernv_defconfig DEFCONFIG_riscv = defconfig DEFCONFIG_s390 = defconfig @@ -78,6 +81,7 @@ QEMU_ARCH_arm64 = aarch64 QEMU_ARCH_arm = arm QEMU_ARCH_mips = mipsel # works with malta_defconfig QEMU_ARCH_ppc = ppc +QEMU_ARCH_ppc64 = ppc64 QEMU_ARCH_ppc64le = ppc64le QEMU_ARCH_riscv = riscv64 QEMU_ARCH_s390 = s390x @@ -92,6 +96,7 @@ QEMU_ARGS_arm64 = -M virt -cpu cortex-a53 -append "panic=-1 $(TEST:%=NOLIBC QEMU_ARGS_arm = -M virt -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" QEMU_ARGS_mips = -M malta -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)" QEMU_ARGS_ppc = -M g3beige -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" +QEMU_ARGS_ppc64 = -M powernv -append "console=hvc0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" QEMU_ARGS_ppc64le = -M powernv -append "console=hvc0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" QEMU_ARGS_riscv = -M virt -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" QEMU_ARGS_s390 = -M s390-ccw-virtio -m 1G -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)" @@ -109,6 +114,7 @@ Q=@ endif CFLAGS_ppc = -m32 -mbig-endian -mno-vsx $(call cc-option,-mmultiple) +CFLAGS_ppc64 = -m64 -mbig-endian -mno-vsx $(call cc-option,-mmultiple) CFLAGS_ppc64le = -m64 -mlittle-endian -mno-vsx $(call cc-option,-mabi=elfv2) CFLAGS_s390 = -m64 CFLAGS_mips = -EL -- cgit v1.2.3 From ce1bb82b1c53585e781e9ec0bf22df23aff104c6 Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Sat, 5 Aug 2023 14:11:02 +0800 Subject: selftests/nolibc: allow report with existing test log MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After the tests finish, it is valuable to report and summarize with existing test log. This avoid rerun or run the tests again when not necessary. Reviewed-by: Thomas Weißschuh Signed-off-by: Zhangjin Wu Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/Makefile | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/Makefile b/tools/testing/selftests/nolibc/Makefile index f7eff081f41f..56abe044173c 100644 --- a/tools/testing/selftests/nolibc/Makefile +++ b/tools/testing/selftests/nolibc/Makefile @@ -216,6 +216,10 @@ rerun: $(Q)qemu-system-$(QEMU_ARCH) -display none -no-reboot -kernel "$(srctree)/$(IMAGE)" -serial stdio $(QEMU_ARGS) > "$(CURDIR)/run.out" $(Q)$(REPORT) $(CURDIR)/run.out +# report with existing test log +report: + $(Q)$(REPORT) $(CURDIR)/run.out + clean: $(call QUIET_CLEAN, sysroot) $(Q)rm -rf sysroot -- cgit v1.2.3 From 418c846821506d01882a948ce90947f264afc606 Mon Sep 17 00:00:00 2001 From: Zhangjin Wu Date: Sat, 12 Aug 2023 04:30:25 +0800 Subject: selftests/nolibc: libc-test: use HOSTCC instead of CC libc-test is mainly added to compare the behavior of nolibc to the system libc, it is meaningless and error-prone with cross compiling. Let's use HOSTCC instead of CC to avoid wrongly use cross compiler when CROSS_COMPILE is passed or customized. Signed-off-by: Zhangjin Wu Fixes: cfb672f94f6e ("selftests/nolibc: add run-libc-test target") Signed-off-by: Willy Tarreau --- tools/testing/selftests/nolibc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/nolibc/Makefile b/tools/testing/selftests/nolibc/Makefile index 56abe044173c..dfe66776a331 100644 --- a/tools/testing/selftests/nolibc/Makefile +++ b/tools/testing/selftests/nolibc/Makefile @@ -178,7 +178,7 @@ nolibc-test: nolibc-test.c endif libc-test: nolibc-test.c - $(QUIET_CC)$(CC) -o $@ $< + $(QUIET_CC)$(HOSTCC) -o $@ $< # local libc-test run-libc-test: libc-test -- cgit v1.2.3