tst-support_descriptors.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /* Tests for monitoring file descriptor usage.
  2. Copyright (C) 2018-2019 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. <http://www.gnu.org/licenses/>. */
  15. #include <fcntl.h>
  16. #include <stdbool.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <support/capture_subprocess.h>
  20. #include <support/check.h>
  21. #include <support/descriptors.h>
  22. #include <support/support.h>
  23. #include <support/xunistd.h>
  24. /* This is the next free descriptor that the subprocess will pick. */
  25. static int free_descriptor;
  26. static void
  27. subprocess_no_change (void *closure)
  28. {
  29. struct support_descriptors *descrs = support_descriptors_list ();
  30. int fd = xopen ("/dev/null", O_WRONLY, 0);
  31. TEST_COMPARE (fd, free_descriptor);
  32. xclose (fd);
  33. support_descriptors_free (descrs);
  34. }
  35. static void
  36. subprocess_closed_descriptor (void *closure)
  37. {
  38. int fd = xopen ("/dev/null", O_WRONLY, 0);
  39. TEST_COMPARE (fd, free_descriptor);
  40. struct support_descriptors *descrs = support_descriptors_list ();
  41. xclose (fd);
  42. support_descriptors_check (descrs); /* Will report failure. */
  43. puts ("EOT");
  44. support_descriptors_free (descrs);
  45. }
  46. static void
  47. subprocess_opened_descriptor (void *closure)
  48. {
  49. struct support_descriptors *descrs = support_descriptors_list ();
  50. int fd = xopen ("/dev/null", O_WRONLY, 0);
  51. TEST_COMPARE (fd, free_descriptor);
  52. support_descriptors_check (descrs); /* Will report failure. */
  53. puts ("EOT");
  54. support_descriptors_free (descrs);
  55. }
  56. static void
  57. subprocess_changed_descriptor (void *closure)
  58. {
  59. int fd = xopen ("/dev/null", O_WRONLY, 0);
  60. TEST_COMPARE (fd, free_descriptor);
  61. struct support_descriptors *descrs = support_descriptors_list ();
  62. xclose (fd);
  63. TEST_COMPARE (xopen ("/dev", O_DIRECTORY | O_RDONLY, 0), fd);
  64. support_descriptors_check (descrs); /* Will report failure. */
  65. puts ("EOT");
  66. support_descriptors_free (descrs);
  67. }
  68. static void
  69. report_subprocess_output (const char *name,
  70. struct support_capture_subprocess *proc)
  71. {
  72. printf ("info: BEGIN %s output\n"
  73. "%s"
  74. "info: END %s output\n",
  75. name, proc->out.buffer, name);
  76. }
  77. /* Use an explicit flag to preserve failure status across
  78. support_record_failure_reset calls. */
  79. static bool good = true;
  80. static void
  81. test_run (void)
  82. {
  83. struct support_capture_subprocess proc = support_capture_subprocess
  84. (&subprocess_no_change, NULL);
  85. support_capture_subprocess_check (&proc, "subprocess_no_change",
  86. 0, sc_allow_none);
  87. support_capture_subprocess_free (&proc);
  88. char *expected = xasprintf ("\nDifferences:\n"
  89. "error: descriptor %d was closed\n"
  90. "EOT\n",
  91. free_descriptor);
  92. good = good && !support_record_failure_is_failed ();
  93. proc = support_capture_subprocess (&subprocess_closed_descriptor, NULL);
  94. good = good && support_record_failure_is_failed ();
  95. support_record_failure_reset (); /* Discard the reported error. */
  96. report_subprocess_output ("subprocess_closed_descriptor", &proc);
  97. TEST_VERIFY (strstr (proc.out.buffer, expected) != NULL);
  98. support_capture_subprocess_check (&proc, "subprocess_closed_descriptor",
  99. 0, sc_allow_stdout);
  100. support_capture_subprocess_free (&proc);
  101. free (expected);
  102. expected = xasprintf ("\nDifferences:\n"
  103. "error: descriptor %d was opened (\"/dev/null\")\n"
  104. "EOT\n",
  105. free_descriptor);
  106. good = good && !support_record_failure_is_failed ();
  107. proc = support_capture_subprocess (&subprocess_opened_descriptor, NULL);
  108. good = good && support_record_failure_is_failed ();
  109. support_record_failure_reset (); /* Discard the reported error. */
  110. report_subprocess_output ("subprocess_opened_descriptor", &proc);
  111. TEST_VERIFY (strstr (proc.out.buffer, expected) != NULL);
  112. support_capture_subprocess_check (&proc, "subprocess_opened_descriptor",
  113. 0, sc_allow_stdout);
  114. support_capture_subprocess_free (&proc);
  115. free (expected);
  116. expected = xasprintf ("\nDifferences:\n"
  117. "error: descriptor %d changed from \"/dev/null\""
  118. " to \"/dev\"\n"
  119. "error: descriptor %d changed ino ",
  120. free_descriptor, free_descriptor);
  121. good = good && !support_record_failure_is_failed ();
  122. proc = support_capture_subprocess (&subprocess_changed_descriptor, NULL);
  123. good = good && support_record_failure_is_failed ();
  124. support_record_failure_reset (); /* Discard the reported error. */
  125. report_subprocess_output ("subprocess_changed_descriptor", &proc);
  126. TEST_VERIFY (strstr (proc.out.buffer, expected) != NULL);
  127. support_capture_subprocess_check (&proc, "subprocess_changed_descriptor",
  128. 0, sc_allow_stdout);
  129. support_capture_subprocess_free (&proc);
  130. free (expected);
  131. }
  132. static int
  133. do_test (void)
  134. {
  135. puts ("info: initial descriptor set");
  136. {
  137. struct support_descriptors *descrs = support_descriptors_list ();
  138. support_descriptors_dump (descrs, "info: ", stdout);
  139. support_descriptors_free (descrs);
  140. }
  141. free_descriptor = xopen ("/dev/null", O_WRONLY, 0);
  142. puts ("info: descriptor set with additional free descriptor");
  143. {
  144. struct support_descriptors *descrs = support_descriptors_list ();
  145. support_descriptors_dump (descrs, "info: ", stdout);
  146. support_descriptors_free (descrs);
  147. }
  148. TEST_VERIFY (free_descriptor >= 3);
  149. xclose (free_descriptor);
  150. /* Initial test run without a sentinel descriptor. The presence of
  151. such a descriptor exercises different conditions in the list
  152. comparison in support_descriptors_check. */
  153. test_run ();
  154. /* Allocate a sentinel descriptor at the end of the descriptor list,
  155. after free_descriptor. */
  156. int sentinel_fd;
  157. {
  158. int fd = xopen ("/dev/full", O_WRONLY, 0);
  159. TEST_COMPARE (fd, free_descriptor);
  160. sentinel_fd = dup (fd);
  161. TEST_VERIFY_EXIT (sentinel_fd > fd);
  162. xclose (fd);
  163. }
  164. puts ("info: descriptor set with sentinel descriptor");
  165. {
  166. struct support_descriptors *descrs = support_descriptors_list ();
  167. support_descriptors_dump (descrs, "info: ", stdout);
  168. support_descriptors_free (descrs);
  169. }
  170. /* Second test run with sentinel descriptor. */
  171. test_run ();
  172. xclose (sentinel_fd);
  173. return !good;
  174. }
  175. #include <support/test-driver.c>