1  /* Test support_record_failure state sharing.
       2     Copyright (C) 2016-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <support/check.h>
      20  #include <support/support.h>
      21  #include <support/test-driver.h>
      22  #include <support/xunistd.h>
      23  
      24  #include <getopt.h>
      25  #include <stdbool.h>
      26  #include <stdlib.h>
      27  #include <stdio.h>
      28  #include <string.h>
      29  
      30  static int exit_status_with_failure = -1;
      31  static bool test_verify;
      32  static bool test_verify_exit;
      33  enum
      34    {
      35      OPT_STATUS = 10001,
      36      OPT_TEST_VERIFY,
      37      OPT_TEST_VERIFY_EXIT,
      38    };
      39  #define CMDLINE_OPTIONS                                                 \
      40    { "status", required_argument, NULL, OPT_STATUS },                    \
      41    { "test-verify", no_argument, NULL, OPT_TEST_VERIFY },                \
      42    { "test-verify-exit", no_argument, NULL, OPT_TEST_VERIFY_EXIT },
      43  static void
      44  cmdline_process (int c)
      45  {
      46    switch (c)
      47      {
      48      case OPT_STATUS:
      49        exit_status_with_failure = atoi (optarg);
      50        break;
      51      case OPT_TEST_VERIFY:
      52        test_verify = true;
      53        break;
      54      case OPT_TEST_VERIFY_EXIT:
      55        test_verify_exit = true;
      56        break;
      57      }
      58  }
      59  #define CMDLINE_PROCESS cmdline_process
      60  
      61  static void
      62  check_failure_reporting (int phase, int zero, int unsupported)
      63  {
      64    int status = support_report_failure (0);
      65    if (status != zero)
      66      {
      67        printf ("real-error (phase %d): support_report_failure (0) == %d\n",
      68                phase, status);
      69        exit (1);
      70      }
      71    status = support_report_failure (1);
      72    if (status != 1)
      73      {
      74        printf ("real-error (phase %d): support_report_failure (1) == %d\n",
      75                phase, status);
      76        exit (1);
      77      }
      78    status = support_report_failure (2);
      79    if (status != 2)
      80      {
      81        printf ("real-error (phase %d): support_report_failure (2) == %d\n",
      82                phase, status);
      83        exit (1);
      84      }
      85    status = support_report_failure (EXIT_UNSUPPORTED);
      86    if (status != unsupported)
      87      {
      88        printf ("real-error (phase %d): "
      89                "support_report_failure (EXIT_UNSUPPORTED) == %d\n",
      90                phase, status);
      91        exit (1);
      92      }
      93  }
      94  
      95  static int
      96  do_test (void)
      97  {
      98    if (exit_status_with_failure >= 0)
      99      {
     100        /* External invocation with requested error status.  Used by
     101           tst-support_report_failure-2.sh.  */
     102        support_record_failure ();
     103        return exit_status_with_failure;
     104      }
     105    TEST_VERIFY (true);
     106    TEST_VERIFY_EXIT (true);
     107    if (test_verify)
     108      {
     109        TEST_VERIFY (false);
     110        if (test_verbose)
     111          printf ("info: execution passed failed TEST_VERIFY\n");
     112        return 2; /* Expected exit status.  */
     113      }
     114    if (test_verify_exit)
     115      {
     116        TEST_VERIFY_EXIT (false);
     117        return 3; /* Not reached.  Expected exit status is 1.  */
     118      }
     119  
     120    printf ("info: This test tests the test framework.\n"
     121            "info: It reports some expected errors on stdout.\n");
     122  
     123    /* Check that the status is passed through unchanged.  */
     124    check_failure_reporting (1, 0, EXIT_UNSUPPORTED);
     125  
     126    /* Check state propagation from a subprocess.  */
     127    pid_t pid = xfork ();
     128    if (pid == 0)
     129      {
     130        support_record_failure ();
     131        _exit (0);
     132      }
     133    int status;
     134    xwaitpid (pid, &status, 0);
     135    if (status != 0)
     136      {
     137        printf ("real-error: incorrect status from subprocess: %d\n", status);
     138        return 1;
     139      }
     140    check_failure_reporting (2, 1, 1);
     141  
     142    /* Also test directly in the parent process.  */
     143    support_record_failure_reset ();
     144    check_failure_reporting (3, 0, EXIT_UNSUPPORTED);
     145    support_record_failure ();
     146    check_failure_reporting (4, 1, 1);
     147  
     148    /* We need to mask the failure above.  */
     149    support_record_failure_reset ();
     150    return 0;
     151  }
     152  
     153  #include <support/test-driver.c>