Home | History | Annotate | Download | only in testsuite
      1 /* expandargv test program,
      2    Copyright (C) 2006 Free Software Foundation, Inc.
      3    Written by Carlos O'Donell <carlos (at) 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 
    335