test-assert-2.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /* Test assert's compliance with POSIX requirements.
  2. Copyright (C) 2024-2026 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <https://www.gnu.org/licenses/>. */
  15. /* This test verifies that a failed assertion acts in accordance with
  16. the POSIX requirements, despite any internal failures. We do so by
  17. calling test routines via fork() and monitoring their exit codes
  18. and stderr, while possibly forcing internal functions (malloc) to
  19. fail. */
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <dlfcn.h>
  23. #include <string.h>
  24. #include <signal.h>
  25. #include <unistd.h>
  26. #undef NDEBUG
  27. #include <assert.h>
  28. #include <support/check.h>
  29. #include <support/support.h>
  30. #include <support/capture_subprocess.h>
  31. #include <support/xstdio.h>
  32. /* We need to be able to make malloc() "fail" so that __asprintf
  33. fails. */
  34. void * (*next_malloc)(size_t sz) = 0;
  35. static volatile bool fail_malloc = 0;
  36. void *
  37. malloc (size_t sz)
  38. {
  39. if (fail_malloc)
  40. return NULL;
  41. if (next_malloc == 0)
  42. next_malloc = dlsym (RTLD_NEXT, "malloc");
  43. if (next_malloc == 0)
  44. return NULL;
  45. return next_malloc (sz);
  46. }
  47. /* We can tell if abort() is called by looking for the custom return
  48. value. */
  49. void
  50. abort_handler(int s)
  51. {
  52. _exit(5);
  53. }
  54. static int do_lineno;
  55. static const char *do_funcname;
  56. /* Hack to get the line of the assert. */
  57. #define GET_INFO_1(l) \
  58. if (closure != NULL) \
  59. { \
  60. do_lineno = l; \
  61. do_funcname = __func__; \
  62. return; \
  63. }
  64. #define GET_INFO() GET_INFO_1(__LINE__+1)
  65. /* These are the two test cases. */
  66. static void
  67. test_assert_normal (void *closure)
  68. {
  69. if (closure == NULL)
  70. signal (SIGABRT, abort_handler);
  71. GET_INFO ();
  72. assert (1 == 2);
  73. }
  74. static void
  75. test_assert_nomalloc (void *closure)
  76. {
  77. if (closure == NULL)
  78. {
  79. signal (SIGABRT, abort_handler);
  80. fail_malloc = 1;
  81. }
  82. GET_INFO ();
  83. assert (1 == 2);
  84. }
  85. static void
  86. check_posix (const char *buf, int rv, int line,
  87. const char *funcname, const char *testarg)
  88. {
  89. /* POSIX requires that a failed assertion write a diagnostic to
  90. stderr and call abort. The diagnostic must include the filename,
  91. line number, and function where the assertion failed, along with
  92. the text of the assert() argument.
  93. */
  94. char linestr[100];
  95. sprintf (linestr, "%d", line);
  96. /* If abort is called, our handler will return 5. */
  97. TEST_VERIFY (rv == 5);
  98. TEST_VERIFY (strstr (buf, __FILE__) != NULL);
  99. TEST_VERIFY (strstr (buf, linestr) != NULL);
  100. TEST_VERIFY (strstr (buf, funcname) != NULL);
  101. TEST_VERIFY (strstr (buf, testarg) != NULL);
  102. }
  103. static void
  104. one_test (void (*func)(void *))
  105. {
  106. struct support_capture_subprocess sp;
  107. int rv;
  108. func (&do_lineno);
  109. printf("running test for %s, line %d\n", do_funcname, do_lineno);
  110. sp = support_capture_subprocess (func, NULL);
  111. rv = WEXITSTATUS (sp.status);
  112. check_posix (sp.err.buffer, rv, do_lineno, do_funcname, "1 == 2");
  113. TEST_VERIFY (strstr (sp.err.buffer, "failed.\n") != NULL);
  114. support_capture_subprocess_free (&sp);
  115. }
  116. static int
  117. do_test(void)
  118. {
  119. one_test (test_assert_normal);
  120. one_test (test_assert_nomalloc);
  121. return 0;
  122. }
  123. #include <support/test-driver.c>