(root)/
binutils-2.41/
libiberty/
testsuite/
test-expandargv.c
       1  /* expandargv test program,
       2     Copyright (C) 2006-2023 Free Software Foundation, Inc.
       3     Written by Carlos O'Donell <carlos@codesourcery.com>
       4  
       5     This file is part of the libiberty library, which is part of GCC.
       6  
       7     This file is free software; you can redistribute it and/or modify
       8     it under the terms of the GNU General Public License as published by
       9     the Free Software Foundation; either version 2 of the License, or
      10     (at your option) any later version.
      11  
      12     In addition to the permissions in the GNU General Public License, the
      13     Free Software Foundation gives you unlimited permission to link the
      14     compiled version of this file into combinations with other programs,
      15     and to distribute those combinations without any restriction coming
      16     from the use of this file.  (The General Public License restrictions
      17     do apply in other respects; for example, they cover modification of
      18     the file, and distribution when not linked into a combined
      19     executable.)
      20  
      21     This program is distributed in the hope that it will be useful,
      22     but WITHOUT ANY WARRANTY; without even the implied warranty of
      23     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      24     GNU General Public License for more details.
      25  
      26     You should have received a copy of the GNU General Public License
      27     along with this program; if not, write to the Free Software
      28     Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. 
      29  */
      30  
      31  #ifdef HAVE_CONFIG_H
      32  #include "config.h"
      33  #endif
      34  #include "libiberty.h"
      35  #include <stdio.h>
      36  #include <errno.h>
      37  #ifdef HAVE_STDLIB_H
      38  #include <stdlib.h>
      39  #endif
      40  #ifdef HAVE_STRING_H
      41  #include <string.h>
      42  #endif
      43  #ifdef HAVE_UNISTD_H
      44  #include <unistd.h>
      45  #endif
      46  
      47  #ifndef EXIT_SUCCESS
      48  #define EXIT_SUCCESS 0
      49  #endif
      50  
      51  #ifndef EXIT_FAILURE
      52  #define EXIT_FAILURE 1
      53  #endif
      54  
      55  static void fatal_error (int, const char *, int) ATTRIBUTE_NORETURN;
      56  void writeout_test (int, const char *);
      57  void run_replaces (char *);
      58  void hook_char_replace (char *, size_t, char, char);
      59  int run_tests (const char **);
      60  void erase_test (int);
      61  
      62  /* Test input data, argv before, and argv after:
      63   
      64     The \n is an important part of test_data since expandargv
      65     may have to work in environments where \n is translated
      66     as \r\n. Thus \n is included in the test data for the file. 
      67  
      68     We use \b to indicate that the test data is the null character.
      69     This is because we use \0 normally to represent the end of the 
      70     file data, so we need something else for this. */
      71  
      72  #define FILENAME_PATTERN "test-expandargv-%d.lst"
      73  #define ARGV0 "test-expandargv"
      74  
      75  const char *test_data[] = {
      76    /* Test 0 - Check for expansion with \r\n */
      77    "a\r\nb",	/* Test 0 data */
      78    ARGV0,
      79    "@test-expandargv-0.lst",
      80    0, /* End of argv[] before expansion */
      81    ARGV0,
      82    "a",
      83    "b",
      84    0, /* End of argv[] after expansion */
      85  
      86    /* Test 1 - Check for expansion with \n */
      87    "a\nb",	/* Test 1 data */
      88    ARGV0,
      89    "@test-expandargv-1.lst",
      90    0,
      91    ARGV0,
      92    "a",
      93    "b",
      94    0,
      95  
      96    /* Test 2 - Check for expansion with \0 */
      97    "a\bb",	/* Test 2 data */
      98    ARGV0,
      99    "@test-expandargv-2.lst",
     100    0,
     101    ARGV0,
     102    "a",
     103    0,
     104  
     105    /* Test 3 - Check for expansion with only \0 */
     106    "\b",		/* Test 3 data */
     107    ARGV0,
     108    "@test-expandargv-3.lst",
     109    0,
     110    ARGV0,
     111    0,
     112  
     113    /* Test 4 - Check for options beginning with an empty line.  */
     114    "\na\nb",	/* Test 4 data */
     115    ARGV0,
     116    "@test-expandargv-4.lst",
     117    0,
     118    ARGV0,
     119    "a",
     120    "b",
     121    0,
     122  
     123    /* Test 5 - Check for options containing an empty argument.  */
     124    "a\n''\nb",    /* Test 5 data */
     125    ARGV0,
     126    "@test-expandargv-5.lst",
     127    0,
     128    ARGV0,
     129    "a",
     130    "",
     131    "b",
     132    0,
     133  
     134    /* Test 6 - Check for options containing a quoted newline.  */
     135    "a\n'a\n\nb'\nb",    /* Test 6 data */
     136    ARGV0,
     137    "@test-expandargv-6.lst",
     138    0,
     139    ARGV0,
     140    "a",
     141    "a\n\nb",
     142    "b",
     143    0,
     144  
     145    0 /* Test done marker, don't remove. */
     146  };
     147  
     148  /* Print a fatal error and exit.  LINE is the line number where we
     149     detected the error, ERRMSG is the error message to print, and ERR
     150     is 0 or an errno value to print.  */
     151  
     152  static void
     153  fatal_error (int line, const char *errmsg, int err)
     154  {
     155    fprintf (stderr, "test-expandargv:%d: %s", line, errmsg);
     156    if (errno != 0)
     157      fprintf (stderr, ": %s", xstrerror (err));
     158    fprintf (stderr, "\n");
     159    exit (EXIT_FAILURE);
     160  }
     161  
     162  /* hook_char_replace:
     163       Replace 'replacethis' with 'withthis' */
     164  
     165  void
     166  hook_char_replace (char *string, size_t len, char replacethis, char withthis)
     167  {
     168    int i = 0;
     169    for (i = 0; i < len; i++)
     170      if (string[i] == replacethis)
     171        string[i] = withthis;
     172  }
     173  
     174  /* run_replaces:
     175       Hook here all the character for character replaces.
     176       Be warned that expanding the string or contracting the string
     177       should be handled with care. */
     178  
     179  void
     180  run_replaces (char * string)
     181  {
     182    /* Store original string size */
     183    size_t len = strlen (string);
     184    hook_char_replace (string, len, '\b', '\0');
     185  }
     186  
     187  /* write_test:
     188     Write test datafile */
     189  
     190  void
     191  writeout_test (int test, const char * test_data)
     192  {
     193    char filename[256];
     194    FILE *fd;
     195    size_t len, sys_fwrite;
     196    char * parse;
     197  
     198    /* Unique filename per test */
     199    sprintf (filename, FILENAME_PATTERN, test);
     200    fd = fopen (filename, "w");
     201    if (fd == NULL)
     202      fatal_error (__LINE__, "Failed to create test file.", errno);
     203  
     204    /* Generate RW copy of data for replaces */
     205    len = strlen (test_data);
     206    parse = malloc (sizeof (char) * (len + 1));
     207    if (parse == NULL)
     208      fatal_error (__LINE__, "Failed to malloc parse.", errno);
     209        
     210    memcpy (parse, test_data, sizeof (char) * (len + 1));
     211    /* Run all possible replaces */
     212    run_replaces (parse);
     213  
     214    sys_fwrite = fwrite (parse, sizeof (char), len, fd);
     215    if (sys_fwrite != len)
     216      fatal_error (__LINE__, "Failed to write to test file.", errno);
     217  
     218    free (parse);
     219    fclose (fd);
     220  }
     221  
     222  /* erase_test:
     223       Erase the test file */
     224  
     225  void 
     226  erase_test (int test)
     227  {
     228    char filename[256]; 
     229    sprintf (filename, FILENAME_PATTERN, test);
     230    if (unlink (filename) != 0)
     231      fatal_error (__LINE__, "Failed to erase test file.", errno);
     232  }
     233  
     234  
     235  /* run_tests:
     236      Run expandargv
     237      Compare argv before and after.
     238      Return number of fails */
     239  
     240  int
     241  run_tests (const char **test_data)
     242  {
     243    int argc_after, argc_before;
     244    char ** argv_before, ** argv_after;
     245    int i, j, k, fails, failed;
     246  
     247    i = j = fails = 0;
     248    /* Loop over all the tests */
     249    while (test_data[j])
     250      {
     251        /* Write test data */
     252        writeout_test (i, test_data[j++]);
     253        /* Copy argv before */
     254        argv_before = dupargv ((char **) &test_data[j]);
     255  
     256        /* Count argc before/after */
     257        argc_before = 0;
     258        argc_after = 0;
     259        while (test_data[j + argc_before])
     260          argc_before++;
     261        j += argc_before + 1; /* Skip null */
     262        while (test_data[j + argc_after])
     263          argc_after++;
     264  
     265        /* Copy argv after */
     266        argv_after = dupargv ((char **) &test_data[j]);
     267  
     268        /* Run all possible replaces */
     269        for (k = 0; k < argc_before; k++)
     270          run_replaces (argv_before[k]);
     271        for (k = 0; k < argc_after; k++)
     272          run_replaces (argv_after[k]);
     273  
     274        /* Run test: Expand arguments */
     275        expandargv (&argc_before, &argv_before);
     276  
     277        failed = 0;
     278        /* Compare size first */
     279        if (argc_before != argc_after)
     280          {
     281            printf ("FAIL: test-expandargv-%d. Number of arguments don't match.\n", i);
     282  	  failed++;
     283          }
     284        /* Compare each of the argv's ... */
     285        else
     286          for (k = 0; k < argc_after; k++)
     287            if (strcmp (argv_before[k], argv_after[k]) != 0)
     288              {
     289                printf ("FAIL: test-expandargv-%d. Arguments don't match.\n", i);
     290                failed++;
     291              }
     292  
     293        if (!failed)
     294          printf ("PASS: test-expandargv-%d.\n", i);
     295        else
     296          fails++;
     297  
     298        freeargv (argv_before);
     299        freeargv (argv_after);
     300        /* Advance to next test */
     301        j += argc_after + 1;
     302        /* Erase test file */
     303        erase_test (i);
     304        i++;
     305      }
     306    return fails;
     307  }
     308  
     309  /* main:
     310      Run tests. 
     311      Check result and exit with appropriate code. */
     312  
     313  int 
     314  main(int argc, char **argv)
     315  {
     316    int fails;
     317    /* Repeat for all the tests:
     318       - Parse data array and write into file.
     319         - Run replace hooks before writing to file.
     320       - Parse data array and build argv before/after.
     321         - Run replace hooks on argv before/after
     322       - Run expandargv.
     323       - Compare output of expandargv argv to after argv.
     324         - If they compare the same then test passes
     325           else the test fails. 
     326       - Erase test file. */
     327  
     328    fails = run_tests (test_data);
     329    if (!fails)
     330      exit (EXIT_SUCCESS);
     331    else
     332      exit (EXIT_FAILURE);
     333  }
     334