Back to index

cell-binutils  2.17cvs20070401
test-expandargv.c
Go to the documentation of this file.
00001 /* expandargv test program,
00002    Copyright (C) 2006 Free Software Foundation, Inc.
00003    Written by Carlos O'Donell <carlos@codesourcery.com>
00004 
00005    This file is part of the libiberty library, which is part of GCC.
00006 
00007    This file is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011 
00012    In addition to the permissions in the GNU General Public License, the
00013    Free Software Foundation gives you unlimited permission to link the
00014    compiled version of this file into combinations with other programs,
00015    and to distribute those combinations without any restriction coming
00016    from the use of this file.  (The General Public License restrictions
00017    do apply in other respects; for example, they cover modification of
00018    the file, and distribution when not linked into a combined
00019    executable.)
00020 
00021    This program is distributed in the hope that it will be useful,
00022    but WITHOUT ANY WARRANTY; without even the implied warranty of
00023    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024    GNU General Public License for more details.
00025 
00026    You should have received a copy of the GNU General Public License
00027    along with this program; if not, write to the Free Software
00028    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. 
00029 */
00030 
00031 #ifdef HAVE_CONFIG_H
00032 #include "config.h"
00033 #endif
00034 #include "libiberty.h"
00035 #include <stdio.h>
00036 #include <errno.h>
00037 #ifdef HAVE_STDLIB_H
00038 #include <stdlib.h>
00039 #endif
00040 #ifdef HAVE_STRING_H
00041 #include <string.h>
00042 #endif
00043 
00044 #ifndef EXIT_SUCCESS
00045 #define EXIT_SUCCESS 0
00046 #endif
00047 
00048 #ifndef EXIT_FAILURE
00049 #define EXIT_FAILURE 1
00050 #endif
00051 
00052 static void fatal_error (int, const char *, int) ATTRIBUTE_NORETURN;
00053 void writeout_test (int, const char *);
00054 void run_replaces (char *);
00055 void hook_char_replace (char *, size_t, char, char);
00056 int run_tests (const char **);
00057 void erase_test (int);
00058 
00059 /* Test input data, argv before, and argv after:
00060  
00061    The \n is an important part of test_data since expandargv
00062    may have to work in environments where \n is translated
00063    as \r\n. Thus \n is included in the test data for the file. 
00064 
00065    We use \b to indicate that the test data is the null character.
00066    This is because we use \0 normally to represent the end of the 
00067    file data, so we need something else for this. */
00068 
00069 #define FILENAME_PATTERN "test-expandargv-%d.lst"
00070 #define ARGV0 "test-expandargv"
00071 
00072 const char *test_data[] = {
00073   /* Test 0 - Check for expansion with \r\n */
00074   "a\r\nb",   /* Test 0 data */
00075   ARGV0,
00076   "@test-expandargv-0.lst",
00077   0, /* End of argv[] before expansion */
00078   ARGV0,
00079   "a",
00080   "b",
00081   0, /* End of argv[] after expansion */
00082 
00083   /* Test 1 - Check for expansion with \n */
00084   "a\nb",     /* Test 1 data */
00085   ARGV0,
00086   "@test-expandargv-1.lst",
00087   0,
00088   ARGV0,
00089   "a",
00090   "b",
00091   0,
00092 
00093   /* Test 2 - Check for expansion with \0 */
00094   "a\bb",     /* Test 2 data */
00095   ARGV0,
00096   "@test-expandargv-2.lst",
00097   0,
00098   ARGV0,
00099   "a",
00100   0,
00101 
00102   /* Test 3 - Check for expansion with only \0 */
00103   "\b",              /* Test 3 data */
00104   ARGV0,
00105   "@test-expandargv-3.lst",
00106   0,
00107   ARGV0,
00108   0,
00109 
00110   0 /* Test done marker, don't remove. */
00111 };
00112 
00113 /* Print a fatal error and exit.  LINE is the line number where we
00114    detected the error, ERRMSG is the error message to print, and ERR
00115    is 0 or an errno value to print.  */
00116 
00117 static void
00118 fatal_error (int line, const char *errmsg, int err)
00119 {
00120   fprintf (stderr, "test-expandargv:%d: %s", line, errmsg);
00121   if (errno != 0)
00122     fprintf (stderr, ": %s", xstrerror (err));
00123   fprintf (stderr, "\n");
00124   exit (EXIT_FAILURE);
00125 }
00126 
00127 /* hook_char_replace:
00128      Replace 'replacethis' with 'withthis' */
00129 
00130 void
00131 hook_char_replace (char *string, size_t len, char replacethis, char withthis)
00132 {
00133   int i = 0;
00134   for (i = 0; i < len; i++)
00135     if (string[i] == replacethis)
00136       string[i] = withthis;
00137 }
00138 
00139 /* run_replaces:
00140      Hook here all the character for character replaces.
00141      Be warned that expanding the string or contracting the string
00142      should be handled with care. */
00143 
00144 void
00145 run_replaces (char * string)
00146 {
00147   /* Store original string size */
00148   size_t len = strlen (string);
00149   hook_char_replace (string, len, '\b', '\0');
00150 }
00151 
00152 /* write_test:
00153    Write test datafile */
00154 
00155 void
00156 writeout_test (int test, const char * test_data)
00157 {
00158   char filename[256];
00159   FILE *fd;
00160   size_t len;
00161   char * parse;
00162 
00163   /* Unique filename per test */
00164   sprintf (filename, FILENAME_PATTERN, test);
00165   fd = fopen (filename, "w");
00166   if (fd == NULL)
00167     fatal_error (__LINE__, "Failed to create test file.", errno);
00168 
00169   /* Generate RW copy of data for replaces */
00170   len = strlen (test_data);
00171   parse = malloc (sizeof (char) * (len + 1));
00172   if (parse == NULL)
00173     fatal_error (__LINE__, "Failed to malloc parse.", errno);
00174       
00175   memcpy (parse, test_data, sizeof (char) * len);
00176   /* Run all possible replaces */
00177   run_replaces (parse);
00178 
00179   fwrite (parse, len, sizeof (char), fd);
00180   free (parse);
00181   fclose (fd);
00182 }
00183 
00184 /* erase_test:
00185      Erase the test file */
00186 
00187 void 
00188 erase_test (int test)
00189 {
00190   char filename[256]; 
00191   sprintf (filename, FILENAME_PATTERN, test);
00192   if (unlink (filename) != 0)
00193     fatal_error (__LINE__, "Failed to erase test file.", errno);
00194 }
00195 
00196 
00197 /* run_tests:
00198     Run expandargv
00199     Compare argv before and after.
00200     Return number of fails */
00201 
00202 int
00203 run_tests (const char **test_data)
00204 {
00205   int argc_after, argc_before;
00206   char ** argv_before, ** argv_after;
00207   int i, j, k, fails, failed;
00208 
00209   i = j = fails = 0;
00210   /* Loop over all the tests */
00211   while (test_data[j])
00212     {
00213       /* Write test data */
00214       writeout_test (i, test_data[j++]);
00215       /* Copy argv before */
00216       argv_before = dupargv ((char **) &test_data[j]);
00217 
00218       /* Count argc before/after */
00219       argc_before = 0;
00220       argc_after = 0;
00221       while (test_data[j + argc_before])
00222         argc_before++;
00223       j += argc_before + 1; /* Skip null */
00224       while (test_data[j + argc_after])
00225         argc_after++;
00226 
00227       /* Copy argv after */
00228       argv_after = dupargv ((char **) &test_data[j]);
00229 
00230       /* Run all possible replaces */
00231       for (k = 0; k < argc_before; k++)
00232         run_replaces (argv_before[k]);
00233       for (k = 0; k < argc_after; k++)
00234         run_replaces (argv_after[k]);
00235 
00236       /* Run test: Expand arguments */
00237       expandargv (&argc_before, &argv_before);
00238 
00239       failed = 0;
00240       /* Compare size first */
00241       if (argc_before != argc_after)
00242         {
00243           printf ("FAIL: test-expandargv-%d. Number of arguments don't match.\n", i);
00244          failed++;
00245         }
00246       /* Compare each of the argv's ... */
00247       else
00248         for (k = 0; k < argc_after; k++)
00249           if (strncmp (argv_before[k], argv_after[k], strlen(argv_after[k])) != 0)
00250             {
00251               printf ("FAIL: test-expandargv-%d. Arguments don't match.\n", i);
00252               failed++;
00253             }
00254 
00255       if (!failed)
00256         printf ("PASS: test-expandargv-%d.\n", i);
00257       else
00258         fails++;
00259 
00260       freeargv (argv_before);
00261       freeargv (argv_after);
00262       /* Advance to next test */
00263       j += argc_after + 1;
00264       /* Erase test file */
00265       erase_test (i);
00266       i++;
00267     }
00268   return fails;
00269 }
00270 
00271 /* main:
00272     Run tests. 
00273     Check result and exit with appropriate code. */
00274 
00275 int 
00276 main(int argc, char **argv)
00277 {
00278   int fails;
00279   /* Repeat for all the tests:
00280      - Parse data array and write into file.
00281        - Run replace hooks before writing to file.
00282      - Parse data array and build argv before/after.
00283        - Run replace hooks on argv before/after
00284      - Run expandargv.
00285      - Compare output of expandargv argv to after argv.
00286        - If they compare the same then test passes
00287          else the test fails. 
00288      - Erase test file. */
00289 
00290   fails = run_tests (test_data);
00291   if (!fails)
00292     exit (EXIT_SUCCESS);
00293   else
00294     exit (EXIT_FAILURE);
00295 }
00296