From 759712ba05089a91c681fa93fc4e351aae7f7bbe Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Sat, 25 Jun 2022 18:13:18 +0100 Subject: [PATCH] zuc: Delete support for forking tests ZUC's default mode is to fork for every test case. Unfortunately on AArch64, fork in an ASan-traced program usually takes around 3.6 entire seconds. This was leading to the config-parser test timing out. As none of our remaining ZUC tests even need to fork, just remove all support for it. Signed-off-by: Daniel Stone --- tests/meson.build | 2 - tools/zunitc/inc/zunitc/zunitc.h | 10 - tools/zunitc/src/zuc_collector.c | 427 ------------------------------- tools/zunitc/src/zuc_collector.h | 58 ----- tools/zunitc/src/zuc_context.h | 2 - tools/zunitc/src/zunitc_impl.c | 136 +--------- 6 files changed, 6 insertions(+), 629 deletions(-) delete mode 100644 tools/zunitc/src/zuc_collector.c delete mode 100644 tools/zunitc/src/zuc_collector.h diff --git a/tests/meson.build b/tests/meson.build index 06479710..fe107334 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -107,8 +107,6 @@ lib_zuc = static_library( '../tools/zunitc/inc/zunitc/zunitc_impl.h', '../tools/zunitc/src/zuc_base_logger.c', '../tools/zunitc/src/zuc_base_logger.h', - '../tools/zunitc/src/zuc_collector.c', - '../tools/zunitc/src/zuc_collector.h', '../tools/zunitc/src/zuc_context.h', '../tools/zunitc/src/zuc_event.h', '../tools/zunitc/src/zuc_event_listener.h', diff --git a/tools/zunitc/inc/zunitc/zunitc.h b/tools/zunitc/inc/zunitc/zunitc.h index 16b211ba..d285c59d 100644 --- a/tools/zunitc/inc/zunitc/zunitc.h +++ b/tools/zunitc/inc/zunitc/zunitc.h @@ -239,16 +239,6 @@ zuc_set_repeat(int repeat); void zuc_set_random(int random); -/** - * Controls whether or not to run the tests as forked child processes. - * Defaults to true. - * - * @param spawn true to spawn each test in a forked child process, - * false to run tests directly. - */ -void -zuc_set_spawn(bool spawn); - /** * Enables output in the JUnit XML format. * Defaults to false. diff --git a/tools/zunitc/src/zuc_collector.c b/tools/zunitc/src/zuc_collector.c deleted file mode 100644 index 035c9ce7..00000000 --- a/tools/zunitc/src/zuc_collector.c +++ /dev/null @@ -1,427 +0,0 @@ -/* - * Copyright © 2015 Samsung Electronics Co., Ltd - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "config.h" - -#include "zuc_collector.h" - -#include -#include -#include -#include - -#include -#include "zuc_event_listener.h" -#include "zunitc/zunitc_impl.h" - -#include -#include -#include - -/** - * @file - * General handling of collecting events during testing to pass back to - * main tracking of fork()'d tests. - * - * @note implementation of zuc_process_message() is included here so that - * all child->parent IPC is in a single source file for easier maintenance - * and updating. - */ - -/** - * Internal data struct for processing. - */ -struct collector_data -{ - int *fd; /**< file descriptor to output to. */ - struct zuc_test *test; /**< current test, or NULL. */ -}; - -/** - * Stores an int32_t into the given buffer. - * - * @param ptr the buffer to store to. - * @param val the value to store. - * @return a pointer to the position in the buffer after the stored value. - */ -static char * -pack_int32(char *ptr, int32_t val); - -/** - * Stores an intptr_t into the given buffer. - * - * @param ptr the buffer to store to. - * @param val the value to store. - * @return a pointer to the position in the buffer after the stored value. - */ -static char * -pack_intptr_t(char *ptr, intptr_t val); - -/** - * Extracts a int32_t from the given buffer. - * - * @param ptr the buffer to extract from. - * @param val the value to set. - * @return a pointer to the position in the buffer after the extracted - * value. - */ -static char const * -unpack_int32(char const *ptr, int32_t *val); - -/** - * Extracts a intptr_t from the given buffer. - * - * @param ptr the buffer to extract from. - * @param val the value to set. - * @return a pointer to the position in the buffer after the extracted - * value. - */ -static char const * -unpack_intptr_t(char const *ptr, intptr_t *val); - -/** - * Extracts a length-prefixed string from the given buffer. - * - * @param ptr the buffer to extract from. - * @param str the value to set. - * @return a pointer to the position in the buffer after the extracted - * value. - */ -static char const * -unpack_string(char const *ptr, char **str); - -/** - * Extracts an event from the given buffer. - * - * @param ptr the buffer to extract from. - * @param len the length of the given buffer. - * @return an event that was packed in the buffer - */ -static struct zuc_event * -unpack_event(char const *ptr, int32_t len); - -/** - * Handles an event by either attaching it directly or sending it over IPC - * as needed. - */ -static void -store_event(struct collector_data *cdata, - enum zuc_event_type event_type, char const *file, int line, - enum zuc_fail_state state, enum zuc_check_op op, - enum zuc_check_valtype valtype, - intptr_t val1, intptr_t val2, const char *expr1, const char *expr2); - -static void -destroy(void *data); - -static void -test_started(void *data, struct zuc_test *test); - -static void -test_ended(void *data, struct zuc_test *test); - -static void -check_triggered(void *data, char const *file, int line, - enum zuc_fail_state state, enum zuc_check_op op, - enum zuc_check_valtype valtype, - intptr_t val1, intptr_t val2, - const char *expr1, const char *expr2); - -static void -collect_event(void *data, char const *file, int line, const char *expr1); - -struct zuc_event_listener * -zuc_collector_create(int *pipe_fd) -{ - struct zuc_event_listener *listener = - zalloc(sizeof(struct zuc_event_listener)); - - listener->data = zalloc(sizeof(struct collector_data)); - ((struct collector_data *)listener->data)->fd = pipe_fd; - listener->destroy = destroy; - listener->test_started = test_started; - listener->test_ended = test_ended; - listener->check_triggered = check_triggered; - listener->collect_event = collect_event; - - return listener; -} - -char * -pack_int32(char *ptr, int32_t val) -{ - memcpy(ptr, &val, sizeof(val)); - return ptr + sizeof(val); -} - -char * -pack_intptr_t(char *ptr, intptr_t val) -{ - memcpy(ptr, &val, sizeof(val)); - return ptr + sizeof(val); -} - -static char * -pack_cstr(char *ptr, intptr_t val, int len) -{ - if (val == 0) { /* a null pointer */ - ptr = pack_int32(ptr, -1); - } else { - ptr = pack_int32(ptr, len); - memcpy(ptr, (const char *)val, len); - ptr += len; - } - return ptr; -} - -void -destroy(void *data) -{ - free(data); -} - -void -test_started(void *data, struct zuc_test *test) -{ - struct collector_data *cdata = data; - cdata->test = test; -} - -void -test_ended(void *data, struct zuc_test *test) -{ - struct collector_data *cdata = data; - cdata->test = NULL; -} - -void -check_triggered(void *data, char const *file, int line, - enum zuc_fail_state state, enum zuc_check_op op, - enum zuc_check_valtype valtype, - intptr_t val1, intptr_t val2, - const char *expr1, const char *expr2) -{ - struct collector_data *cdata = data; - if (op != ZUC_OP_TRACEPOINT) - store_event(cdata, ZUC_EVENT_IMMEDIATE, file, line, state, op, - valtype, - val1, val2, expr1, expr2); -} - -void -collect_event(void *data, char const *file, int line, const char *expr1) -{ - struct collector_data *cdata = data; - store_event(cdata, ZUC_EVENT_DEFERRED, file, line, ZUC_CHECK_OK, - ZUC_OP_TRACEPOINT, ZUC_VAL_INT, - 0, 0, expr1, ""); -} - -void -store_event(struct collector_data *cdata, - enum zuc_event_type event_type, char const *file, int line, - enum zuc_fail_state state, enum zuc_check_op op, - enum zuc_check_valtype valtype, - intptr_t val1, intptr_t val2, const char *expr1, const char *expr2) -{ - struct zuc_event *event = zalloc(sizeof(*event)); - event->file = strdup(file); - event->line = line; - event->state = state; - event->op = op; - event->valtype = valtype; - event->val1 = val1; - event->val2 = val2; - if (valtype == ZUC_VAL_CSTR) { - if (val1) - event->val1 = (intptr_t)strdup((const char *)val1); - if (val2) - event->val2 = (intptr_t)strdup((const char *)val2); - } - event->expr1 = strdup(expr1); - event->expr2 = strdup(expr2); - - zuc_attach_event(cdata->test, event, event_type, false); - - if (*cdata->fd == -1) { - } else { - /* Need to pass it back */ - int sent; - int count; - int expr1_len = strlen(expr1); - int expr2_len = strlen(expr2); - int val1_len = - ((valtype == ZUC_VAL_CSTR) && val1) ? - strlen((char *)val1) : 0; - int val2_len = - ((valtype == ZUC_VAL_CSTR) && val2) ? - strlen((char *)val2) : 0; - int file_len = strlen(file); - int len = (sizeof(int32_t) * 9) + file_len - + (sizeof(intptr_t) * 2) - + ((valtype == ZUC_VAL_CSTR) ? - (sizeof(int32_t) * 2) + val1_len + val2_len : 0) - + expr1_len + expr2_len; - char *buf = zalloc(len); - - char *ptr = pack_int32(buf, len - 4); - ptr = pack_int32(ptr, event_type); - ptr = pack_int32(ptr, file_len); - memcpy(ptr, file, file_len); - ptr += file_len; - ptr = pack_int32(ptr, line); - ptr = pack_int32(ptr, state); - ptr = pack_int32(ptr, op); - ptr = pack_int32(ptr, valtype); - if (valtype == ZUC_VAL_CSTR) { - ptr = pack_cstr(ptr, val1, val1_len); - ptr = pack_cstr(ptr, val2, val2_len); - } else { - ptr = pack_intptr_t(ptr, val1); - ptr = pack_intptr_t(ptr, val2); - } - - ptr = pack_int32(ptr, expr1_len); - if (expr1_len) { - memcpy(ptr, expr1, expr1_len); - ptr += expr1_len; - } - ptr = pack_int32(ptr, expr2_len); - if (expr2_len) { - memcpy(ptr, expr2, expr2_len); - ptr += expr2_len; - } - - - sent = 0; - while (sent < len) { - count = write(*cdata->fd, buf, len); - if (count == -1) - break; - sent += count; - } - - free(buf); - } -} - -char const * -unpack_int32(char const *ptr, int32_t *val) -{ - memcpy(val, ptr, sizeof(*val)); - return ptr + sizeof(*val); -} - -char const * -unpack_intptr_t(char const *ptr, intptr_t *val) -{ - memcpy(val, ptr, sizeof(*val)); - return ptr + sizeof(*val); -} - -char const * -unpack_string(char const *ptr, char **str) -{ - int32_t len = 0; - ptr = unpack_int32(ptr, &len); - *str = zalloc(len + 1); - if (len) - memcpy(*str, ptr, len); - ptr += len; - return ptr; -} - -static char const * -unpack_cstr(char const *ptr, char **str) -{ - int32_t len = 0; - ptr = unpack_int32(ptr, &len); - if (len < 0) { - *str = NULL; - } else { - *str = zalloc(len + 1); - if (len) - memcpy(*str, ptr, len); - ptr += len; - } - return ptr; -} - -struct zuc_event * -unpack_event(char const *ptr, int32_t len) -{ - int32_t val = 0; - struct zuc_event *evt = zalloc(sizeof(*evt)); - char const *tmp = unpack_string(ptr, &evt->file); - tmp = unpack_int32(tmp, &evt->line); - - tmp = unpack_int32(tmp, &val); - evt->state = val; - tmp = unpack_int32(tmp, &val); - evt->op = val; - tmp = unpack_int32(tmp, &val); - evt->valtype = val; - - if (evt->valtype == ZUC_VAL_CSTR) { - char *ptr = NULL; - tmp = unpack_cstr(tmp, &ptr); - evt->val1 = (intptr_t)ptr; - tmp = unpack_cstr(tmp, &ptr); - evt->val2 = (intptr_t)ptr; - } else { - tmp = unpack_intptr_t(tmp, &evt->val1); - tmp = unpack_intptr_t(tmp, &evt->val2); - } - - tmp = unpack_string(tmp, &evt->expr1); - tmp = unpack_string(tmp, &evt->expr2); - - return evt; -} - -int -zuc_process_message(struct zuc_test *test, int fd) -{ - char buf[4] = {}; - int got = read(fd, buf, 4); - if (got == 4) { - enum zuc_event_type event_type = ZUC_EVENT_IMMEDIATE; - int32_t val = 0; - int32_t len = 0; - const char *tmp = NULL; - char *raw = NULL; - unpack_int32(buf, &len); - raw = zalloc(len); - got = read(fd, raw, len); - - tmp = unpack_int32(raw, &val); - event_type = val; - - struct zuc_event *evt = unpack_event(tmp, len - (tmp - raw)); - zuc_attach_event(test, evt, event_type, true); - free(raw); - } - return got; -} diff --git a/tools/zunitc/src/zuc_collector.h b/tools/zunitc/src/zuc_collector.h deleted file mode 100644 index 56f8a5fc..00000000 --- a/tools/zunitc/src/zuc_collector.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright © 2015 Samsung Electronics Co., Ltd - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef ZUC_COLLECTOR_H -#define ZUC_COLLECTOR_H - -struct zuc_event_listener; -struct zuc_test; - -/** - * Creates a new instance of an event collector that will attach events - * to the current test directly or via connection from child to parent. - * - * @param pipe_fd pointer to the file descriptor to use for communication if - * needed. If the value is -1 the events will be attached directly to the - * current test. Otherwise events will be passed back via IPC over this - * pipe with the expectation that the payload will be handled in the parent - * process via zuc_process_message(). - * @return a new collector instance. - * @see zuc_process_message() - */ -struct zuc_event_listener * -zuc_collector_create(int *pipe_fd); - -/** - * Reads events from the given pipe and processes them. - * - * @param test the currently active test to attach events for. - * @param pipe_fd the file descriptor of the pipe to read from. - * @return a positive value if a message was received, 0 if the end has - * been reached and -1 if an error has occurred. - */ -int -zuc_process_message(struct zuc_test *test, int pipe_fd); - -#endif /* ZUC_COLLECTOR_H */ diff --git a/tools/zunitc/src/zuc_context.h b/tools/zunitc/src/zuc_context.h index 609f34bd..c476f5e1 100644 --- a/tools/zunitc/src/zuc_context.h +++ b/tools/zunitc/src/zuc_context.h @@ -42,11 +42,9 @@ struct zuc_context { int repeat; int random; unsigned int seed; - bool spawn; bool break_on_failure; bool output_tap; bool output_junit; - int fds[2]; char *filter; struct zuc_slinked *listeners; diff --git a/tools/zunitc/src/zunitc_impl.c b/tools/zunitc/src/zunitc_impl.c index 395bdd74..18f03015 100644 --- a/tools/zunitc/src/zunitc_impl.c +++ b/tools/zunitc/src/zunitc_impl.c @@ -41,7 +41,6 @@ #include "zunitc/zunitc.h" #include "zuc_base_logger.h" -#include "zuc_collector.h" #include "zuc_context.h" #include "zuc_event_listener.h" #include "zuc_junit_reporter.h" @@ -82,9 +81,7 @@ static struct zuc_context g_ctx = { .fatal = false, .repeat = 0, .random = 0, - .spawn = true, .break_on_failure = false, - .fds = {-1, -1}, .listeners = NULL, @@ -141,12 +138,6 @@ zuc_set_random(int random) g_ctx.random = random; } -void -zuc_set_spawn(bool spawn) -{ - g_ctx.spawn = spawn; -} - void zuc_set_break_on_failure(bool break_on_failure) { @@ -525,7 +516,6 @@ zuc_initialize(int *argc, char *argv[], bool *help_flagged) { int rc = EXIT_FAILURE; bool opt_help = false; - bool opt_nofork = false; bool opt_list = false; int opt_repeat = 0; int opt_random = 0; @@ -537,7 +527,6 @@ zuc_initialize(int *argc, char *argv[], bool *help_flagged) int argc_in = *argc; const struct weston_option options[] = { - { WESTON_OPTION_BOOLEAN, "zuc-nofork", 0, &opt_nofork }, { WESTON_OPTION_BOOLEAN, "zuc-list-tests", 0, &opt_list }, { WESTON_OPTION_INTEGER, "zuc-repeat", 0, &opt_repeat }, { WESTON_OPTION_INTEGER, "zuc-random", 0, &opt_random }, @@ -633,7 +622,6 @@ zuc_initialize(int *argc, char *argv[], bool *help_flagged) " --zuc-break-on-failure\n" " --zuc-filter=FILTER\n" " --zuc-list-tests\n" - " --zuc-nofork\n" #if ENABLE_JUNIT_XML " --zuc-output-xml\n" #endif @@ -650,7 +638,6 @@ zuc_initialize(int *argc, char *argv[], bool *help_flagged) } else { zuc_set_repeat(opt_repeat); zuc_set_random(opt_random); - zuc_set_spawn(!opt_nofork); zuc_set_break_on_failure(opt_break_on_failure); zuc_set_output_junit(opt_junit); rc = EXIT_SUCCESS; @@ -937,11 +924,6 @@ zuc_cleanup(void) free(g_ctx.filter); g_ctx.filter = 0; - for (i = 0; i < 2; ++i) - if (g_ctx.fds[i] != -1) { - close(g_ctx.fds[i]); - g_ctx.fds[i] = -1; - } if (g_ctx.listeners) { struct zuc_slinked *curr = g_ctx.listeners; @@ -1017,108 +999,9 @@ zuc_list_tests(void) } } -static void -spawn_test(struct zuc_test *test, void *test_data, - void (*cleanup_fn)(void *data), void *cleanup_data) -{ - pid_t pid = -1; - - if (!test || (!test->fn && !test->fn_f)) - return; - - if (pipe2(g_ctx.fds, O_CLOEXEC)) { - printf("%s:%d: error: Unable to create pipe: %d\n", - __FILE__, __LINE__, errno); - mark_failed(test, ZUC_CHECK_ERROR); - return; - } - - fflush(NULL); /* important. avoid duplication of output */ - pid = fork(); - switch (pid) { - case -1: /* Error forking */ - printf("%s:%d: error: Problem with fork: %d\n", - __FILE__, __LINE__, errno); - mark_failed(test, ZUC_CHECK_ERROR); - close(g_ctx.fds[0]); - g_ctx.fds[0] = -1; - close(g_ctx.fds[1]); - g_ctx.fds[1] = -1; - break; - case 0: { /* child */ - int rc = EXIT_SUCCESS; - close(g_ctx.fds[0]); - g_ctx.fds[0] = -1; - - if (test->fn_f) - test->fn_f(test_data); - else - test->fn(); - - if (test_has_failure(test)) - rc = EXIT_FAILURE; - else if (test_has_skip(test)) - rc = ZUC_EXIT_SKIP; - - /* Avoid confusing memory tools like valgrind */ - if (cleanup_fn) - cleanup_fn(cleanup_data); - - zuc_cleanup(); - exit(rc); - } - default: { /* parent */ - ssize_t rc = 0; - siginfo_t info = {}; - - close(g_ctx.fds[1]); - g_ctx.fds[1] = -1; - - do { - rc = zuc_process_message(g_ctx.curr_test, - g_ctx.fds[0]); - } while (rc > 0); - close(g_ctx.fds[0]); - g_ctx.fds[0] = -1; - - if (waitid(P_ALL, 0, &info, WEXITED)) { - printf("%s:%d: error: waitid failed. (%d)\n", - __FILE__, __LINE__, errno); - mark_failed(test, ZUC_CHECK_ERROR); - } else { - switch (info.si_code) { - case CLD_EXITED: { - int exit_code = info.si_status; - switch(exit_code) { - case EXIT_SUCCESS: - break; - case ZUC_EXIT_SKIP: - if (!test_has_skip(g_ctx.curr_test) && - !test_has_failure(g_ctx.curr_test)) - ZUC_SKIP("Child exited SKIP"); - break; - default: - /* unexpected failure */ - if (!test_has_failure(g_ctx.curr_test)) - ZUC_ASSERT_EQ(0, exit_code); - } - break; - } - case CLD_KILLED: - case CLD_DUMPED: - printf("%s:%d: error: signaled: %d\n", - __FILE__, __LINE__, info.si_status); - mark_failed(test, ZUC_CHECK_ERROR); - break; - } - } - } - } -} - static void run_single_test(struct zuc_test *test,const struct zuc_fixture *fxt, - void *case_data, bool spawn) + void *case_data) { long elapsed = 0; struct timespec begin; @@ -1146,15 +1029,10 @@ run_single_test(struct zuc_test *test,const struct zuc_fixture *fxt, /* Need to re-check these, as fixtures might have changed test state. */ if (!test->fatal && !test->skipped) { - if (spawn) { - spawn_test(test, test_data, - cleanup_fn, cleanup_data); - } else { - if (test->fn_f) - test->fn_f(test_data); - else - test->fn(); - } + if (test->fn_f) + test->fn_f(test_data); + else + test->fn(); } clock_gettime(TARGET_TIMER, &end); @@ -1204,8 +1082,7 @@ run_single_case(struct zuc_case *test_case) if (curr->disabled) { dispatch_test_disabled(&g_ctx, curr); } else { - run_single_test(curr, fxt, case_data, - g_ctx.spawn); + run_single_test(curr, fxt, case_data); if (curr->skipped) test_case->skipped++; if (curr->failed) @@ -1313,7 +1190,6 @@ zucimpl_run_tests(void) return EXIT_FAILURE; if (g_ctx.listeners == NULL) { - zuc_add_event_listener(zuc_collector_create(&(g_ctx.fds[1]))); zuc_add_event_listener(zuc_base_logger_create()); if (g_ctx.output_junit) zuc_add_event_listener(zuc_junit_reporter_create());