diff --git a/include/crm/common/Makefile.am b/include/crm/common/Makefile.am index dcfe7ce926..e181123358 100644 --- a/include/crm/common/Makefile.am +++ b/include/crm/common/Makefile.am @@ -1,53 +1,54 @@ # # Copyright 2004-2022 the Pacemaker project contributors # # The version control history for this file may have further details. # # This source code is licensed under the GNU General Public License version 2 # or later (GPLv2+) WITHOUT ANY WARRANTY. # MAINTAINERCLEANFILES = Makefile.in headerdir=$(pkgincludedir)/crm/common header_HEADERS = acl.h \ agents.h \ agents_compat.h \ cib.h \ ipc.h \ ipc_attrd_internal.h \ ipc_controld.h \ ipc_pacemakerd.h \ ipc_schedulerd.h \ iso8601.h \ logging.h \ logging_compat.h \ mainloop.h \ mainloop_compat.h \ nvpair.h \ output.h \ results.h \ results_compat.h \ util.h \ util_compat.h \ xml.h \ xml_compat.h noinst_HEADERS = acl_internal.h \ alerts_internal.h \ attrd_internal.h \ cmdline_internal.h \ health_internal.h \ internal.h \ ipc_internal.h \ iso8601_internal.h \ lists_internal.h \ logging_internal.h \ messages_internal.h \ options_internal.h \ output_internal.h \ remote_internal.h \ results_internal.h \ strings_internal.h \ + unittest_internal.h \ xml_internal.h diff --git a/include/crm/common/unittest_internal.h b/include/crm/common/unittest_internal.h new file mode 100644 index 0000000000..a29772c45f --- /dev/null +++ b/include/crm/common/unittest_internal.h @@ -0,0 +1,50 @@ +/* + * Copyright 2022 the Pacemaker project contributors + * + * The version control history for this file may have further details. + * + * This source code is licensed under the GNU Lesser General Public License + * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. + */ + +#include +#include +#include +#include +#include + +#ifndef CRM_COMMON_UNITTEST_INTERNAL__H +#define CRM_COMMON_UNITTEST_INTERNAL__H + +/* internal unit testing related utilities */ + +/* A cmocka-like assert macro for use in unit testing. This one verifies that + * an expression aborts through CRM_ASSERT, erroring out if that is not the case. + * + * This macro works by running the expression in a forked child process with core + * dumps disabled (CRM_ASSERT calls abort(), which will write out a core dump). + * The parent waits for the child to exit and checks why. If the child received + * a SIGABRT, the test passes. For all other cases, the test fails. + */ +#define pcmk__assert_asserts(expr) \ + do { \ + pid_t p = fork(); \ + if (p == 0) { \ + struct rlimit cores = { 0, 0 }; \ + setrlimit(RLIMIT_CORE, &cores); \ + expr; \ + _exit(0); \ + } else if (p > 0) { \ + int wstatus = 0; \ + if (waitpid(p, &wstatus, 0) == -1) { \ + fail_msg("waitpid failed"); \ + } \ + if (!(WIFSIGNALED(wstatus) && WTERMSIG(wstatus) == SIGABRT)) { \ + fail_msg("expr terminated without asserting"); \ + } \ + } else { \ + fail_msg("unable to fork for assert test"); \ + } \ + } while (0); + +#endif /* CRM_COMMON_UNITTEST_INTERNAL__H */