diff options
author | Luca Dariz <luca@orpolo.org> | 2024-01-11 22:08:57 +0100 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2024-01-13 22:42:53 +0100 |
commit | e813641e2fef0fba5a2de9e5a44fd00ab95a86d0 (patch) | |
tree | c617b8841d38d7aa74f4fccd353b81bab83df11f /tests/testlib.c | |
parent | 7538b56278a95d87b9a4ddec01e5679376cc5b13 (diff) | |
download | gnumach-e813641e2fef0fba5a2de9e5a44fd00ab95a86d0.tar.gz gnumach-e813641e2fef0fba5a2de9e5a44fd00ab95a86d0.tar.bz2 gnumach-e813641e2fef0fba5a2de9e5a44fd00ab95a86d0.zip |
add basic user-space tests with qemu
* configure.ac: move test fragment to have USER32
* tests/Makefrag.am: add user tests
* tests/README: add basic info on how to run and debug user tests
* tests/configfrag.ac: allow the test compiler/flags to be
autoconfigured or customized
* tests/grub.cfg.single.template: add minimal grub config to boot a
module
* tests/include/device/cons.h: add a simplified version of
device/cons.h usable for tests
* tests/include/kern/printf.h: symlink to kern/printf.h
* tests/include/mach/mig_support.h: add basic version for user-space
tests
* tests/include/syscalls.h: add prototypes for syscalls used in tests.
* tests/include/testlib.h: add definitions for common test
functionalities
* tests/include/util/atoi.h: symlink to util/atoi.h
* tests/run-qemu.sh.template: add a simple qemu test runner
* tests/start.S: add arch-specific entry point
* tests/syscalls.S: generate syscalls entry points
* tests/test-hello.c: add basic smoke test
* tests/testlib.c: add the minimal functionality to run a user-space
executable and reboot the system, and some test helpers.
* tests/user-qemu.mk: add rules to build simple user-space test
modules, including generating mig stubs. The tests reuse some kernel
code (like printf(), mach_atoi(), mem*(), str*() functions) so we can
use the freestanding environment and not depend on glibc.
Message-ID: <20240111210907.419689-1-luca@orpolo.org>
Diffstat (limited to 'tests/testlib.c')
-rw-r--r-- | tests/testlib.c | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/tests/testlib.c b/tests/testlib.c new file mode 100644 index 00000000..2eaeb591 --- /dev/null +++ b/tests/testlib.c @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2024 Free Software Foundation + * + * This program is free software ; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation ; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY ; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the program ; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <testlib.h> + +#include <device/cons.h> +#include <mach/kern_return.h> +#include <mach/message.h> +#include <mach/mig_errors.h> +#include <mach/vm_param.h> + +#include <mach.user.h> +#include <mach_host.user.h> + + +static int argc = 0; +static char *argv_unknown[] = {"unknown", "m1", "123", "456"}; +static char **argv = argv_unknown; +static char **envp = NULL; +static int envc = 0; + +static mach_port_t host_priv_port = 1; +static mach_port_t device_master_port = 2; + +void cnputc(char c, vm_offset_t cookie) +{ + char buf[2] = {c, 0}; + mach_print(buf); +} + +mach_port_t host_priv(void) +{ + return host_priv_port; +} + +mach_port_t device_priv(void) +{ + return device_master_port; +} + +void halt() +{ + int ret = host_reboot(host_priv_port, 0); + ASSERT_RET(ret, "host_reboot() failed!"); + while (1) + ; +} + +int msleep(uint32_t timeout) +{ + mach_port_t recv = mach_reply_port(); + return mach_msg(NULL, MACH_RCV_MSG|MACH_RCV_TIMEOUT|MACH_RCV_INTERRUPT, + 0, 0, recv, timeout, MACH_PORT_NULL); +} + +const char* e2s(int err) +{ + const char* s = e2s_gnumach(err); + if (s != NULL) + return s; + else + switch (err) + { + default: return "unknown"; + } +} + +/* + * Minimal _start() for test modules, we just take the arguments from the + * kernel, call main() and reboot. As in glibc, we expect the argument pointer + * as a first asrgument. + */ +void __attribute__((used, retain)) +c_start(void **argptr) +{ + intptr_t* argcptr = (intptr_t*)argptr; + argc = argcptr[0]; + argv = (char **) &argcptr[1]; + envp = &argv[argc + 1]; + envc = 0; + + while (envp[envc]) + ++envc; + + mach_atoi(argv[1], &host_priv_port); + mach_atoi(argv[2], &device_master_port); + + printf("started %s", argv[0]); + for (int i=1; i<argc; i++) + { + printf(" %s", argv[i]); + } + printf("\n"); + + int ret = main(argc, argv, envc, envp); + + printf("%s: test %s exit code %x\n", TEST_SUCCESS_MARKER, argv[0], ret); + halt(); +} |