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