aboutsummaryrefslogtreecommitdiff
path: root/assert/test-assert-2.c
diff options
context:
space:
mode:
Diffstat (limited to 'assert/test-assert-2.c')
-rw-r--r--assert/test-assert-2.c167
1 files changed, 167 insertions, 0 deletions
diff --git a/assert/test-assert-2.c b/assert/test-assert-2.c
new file mode 100644
index 0000000..6d54ef9
--- /dev/null
+++ b/assert/test-assert-2.c
@@ -0,0 +1,167 @@
+/* Test assert's compliance with POSIX requirements.
+ Copyright (C) 2024-2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* This test verifies that a failed assertion acts in accordance with
+ the POSIX requirements, despite any internal failures. We do so by
+ calling test routines via fork() and monitoring their exit codes
+ and stderr, while possibly forcing internal functions (malloc) to
+ fail. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+
+#undef NDEBUG
+#include <assert.h>
+
+#include <support/check.h>
+#include <support/support.h>
+#include <support/capture_subprocess.h>
+#include <support/xstdio.h>
+
+/* We need to be able to make malloc() "fail" so that __asprintf
+ fails. */
+
+void * (*next_malloc)(size_t sz) = 0;
+static volatile bool fail_malloc = 0;
+
+void *
+malloc (size_t sz)
+{
+ if (fail_malloc)
+ return NULL;
+ if (next_malloc == 0)
+ next_malloc = dlsym (RTLD_NEXT, "malloc");
+ if (next_malloc == 0)
+ return NULL;
+ return next_malloc (sz);
+}
+
+/* We can tell if abort() is called by looking for the custom return
+ value. */
+
+void
+abort_handler(int s)
+{
+ _exit(5);
+}
+
+static int do_lineno;
+static const char *do_funcname;
+
+/* Hack to get the line of the assert. */
+#define GET_INFO_1(l) \
+ if (closure != NULL) \
+ { \
+ do_lineno = l; \
+ do_funcname = __func__; \
+ return; \
+ }
+#define GET_INFO() GET_INFO_1(__LINE__+1)
+
+/* These are the two test cases. */
+
+static void
+test_assert_normal (void *closure)
+{
+ if (closure == NULL)
+ signal (SIGABRT, abort_handler);
+
+ GET_INFO ();
+ assert (1 == 2);
+}
+
+
+static void
+test_assert_nomalloc (void *closure)
+{
+ if (closure == NULL)
+ {
+ signal (SIGABRT, abort_handler);
+ fail_malloc = 1;
+ }
+
+ GET_INFO ();
+ assert (1 == 2);
+}
+
+static void
+check_posix (const char *buf, int rv, int line,
+ const char *funcname, const char *testarg)
+{
+ /* POSIX requires that a failed assertion write a diagnostic to
+ stderr and call abort. The diagnostic must include the filename,
+ line number, and function where the assertion failed, along with
+ the text of the assert() argument.
+ */
+ char linestr[100];
+
+ sprintf (linestr, "%d", line);
+
+ /* If abort is called, our handler will return 5. */
+ TEST_VERIFY (rv == 5);
+
+ TEST_VERIFY (strstr (buf, __FILE__) != NULL);
+ TEST_VERIFY (strstr (buf, linestr) != NULL);
+ TEST_VERIFY (strstr (buf, funcname) != NULL);
+ TEST_VERIFY (strstr (buf, testarg) != NULL);
+
+}
+
+static void
+one_test (void (*func)(void *), int which_path)
+{
+ struct support_capture_subprocess sp;
+ int rv;
+
+ func (&do_lineno);
+ printf("running test for %s, line %d\n", do_funcname, do_lineno);
+
+ sp = support_capture_subprocess (func, NULL);
+ rv = WEXITSTATUS (sp.status);
+
+ check_posix (sp.err.buffer, rv, do_lineno, do_funcname, "1 == 2");
+
+ /* Look for intentional subtle differences in messages to verify
+ that the intended code path was taken. */
+ switch (which_path)
+ {
+ case 0:
+ TEST_VERIFY (strstr (sp.err.buffer, "failed.\n") != NULL);
+ break;
+ case 1:
+ TEST_VERIFY (strstr (sp.err.buffer, "failed\n") != NULL);
+ break;
+ }
+
+ support_capture_subprocess_free (&sp);
+}
+
+static int
+do_test(void)
+{
+ one_test (test_assert_normal, 0);
+ one_test (test_assert_nomalloc, 1);
+
+ return 0;
+}
+
+#include <support/test-driver.c>