120fce977Smiod /* expandargv test program,
220fce977Smiod    Copyright (C) 2006 Free Software Foundation, Inc.
320fce977Smiod    Written by Carlos O'Donell <carlos@codesourcery.com>
420fce977Smiod 
520fce977Smiod    This file is part of the libiberty library, which is part of GCC.
620fce977Smiod 
720fce977Smiod    This file is free software; you can redistribute it and/or modify
820fce977Smiod    it under the terms of the GNU General Public License as published by
920fce977Smiod    the Free Software Foundation; either version 2 of the License, or
1020fce977Smiod    (at your option) any later version.
1120fce977Smiod 
1220fce977Smiod    In addition to the permissions in the GNU General Public License, the
1320fce977Smiod    Free Software Foundation gives you unlimited permission to link the
1420fce977Smiod    compiled version of this file into combinations with other programs,
1520fce977Smiod    and to distribute those combinations without any restriction coming
1620fce977Smiod    from the use of this file.  (The General Public License restrictions
1720fce977Smiod    do apply in other respects; for example, they cover modification of
1820fce977Smiod    the file, and distribution when not linked into a combined
1920fce977Smiod    executable.)
2020fce977Smiod 
2120fce977Smiod    This program is distributed in the hope that it will be useful,
2220fce977Smiod    but WITHOUT ANY WARRANTY; without even the implied warranty of
2320fce977Smiod    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2420fce977Smiod    GNU General Public License for more details.
2520fce977Smiod 
2620fce977Smiod    You should have received a copy of the GNU General Public License
2720fce977Smiod    along with this program; if not, write to the Free Software
2820fce977Smiod    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
2920fce977Smiod */
3020fce977Smiod 
3120fce977Smiod #ifdef HAVE_CONFIG_H
3220fce977Smiod #include "config.h"
3320fce977Smiod #endif
3420fce977Smiod #include "libiberty.h"
3520fce977Smiod #include <stdio.h>
3620fce977Smiod #include <errno.h>
3720fce977Smiod #include <stdlib.h>
3820fce977Smiod #include <string.h>
39*0fb20bf6Sbluhm #include <unistd.h>
4020fce977Smiod 
4120fce977Smiod #ifndef EXIT_SUCCESS
4220fce977Smiod #define EXIT_SUCCESS 0
4320fce977Smiod #endif
4420fce977Smiod 
4520fce977Smiod #ifndef EXIT_FAILURE
4620fce977Smiod #define EXIT_FAILURE 1
4720fce977Smiod #endif
4820fce977Smiod 
4920fce977Smiod static void fatal_error (int, const char *, int) ATTRIBUTE_NORETURN;
5020fce977Smiod void writeout_test (int, const char *);
5120fce977Smiod void run_replaces (char *);
5220fce977Smiod void hook_char_replace (char *, size_t, char, char);
5320fce977Smiod int run_tests (const char **);
5420fce977Smiod void erase_test (int);
5520fce977Smiod 
5620fce977Smiod /* Test input data, argv before, and argv after:
5720fce977Smiod 
5820fce977Smiod    The \n is an important part of test_data since expandargv
5920fce977Smiod    may have to work in environments where \n is translated
6020fce977Smiod    as \r\n. Thus \n is included in the test data for the file.
6120fce977Smiod 
6220fce977Smiod    We use \b to indicate that the test data is the null character.
6320fce977Smiod    This is because we use \0 normally to represent the end of the
6420fce977Smiod    file data, so we need something else for this. */
6520fce977Smiod 
6620fce977Smiod #define FILENAME_PATTERN "test-expandargv-%d.lst"
6720fce977Smiod #define ARGV0 "test-expandargv"
6820fce977Smiod 
6920fce977Smiod const char *test_data[] = {
7020fce977Smiod   /* Test 0 - Check for expansion with \r\n */
7120fce977Smiod   "a\r\nb",	/* Test 0 data */
7220fce977Smiod   ARGV0,
7320fce977Smiod   "@test-expandargv-0.lst",
7420fce977Smiod   0, /* End of argv[] before expansion */
7520fce977Smiod   ARGV0,
7620fce977Smiod   "a",
7720fce977Smiod   "b",
7820fce977Smiod   0, /* End of argv[] after expansion */
7920fce977Smiod 
8020fce977Smiod   /* Test 1 - Check for expansion with \n */
8120fce977Smiod   "a\nb",	/* Test 1 data */
8220fce977Smiod   ARGV0,
8320fce977Smiod   "@test-expandargv-1.lst",
8420fce977Smiod   0,
8520fce977Smiod   ARGV0,
8620fce977Smiod   "a",
8720fce977Smiod   "b",
8820fce977Smiod   0,
8920fce977Smiod 
9020fce977Smiod   /* Test 2 - Check for expansion with \0 */
9120fce977Smiod   "a\bb",	/* Test 2 data */
9220fce977Smiod   ARGV0,
9320fce977Smiod   "@test-expandargv-2.lst",
9420fce977Smiod   0,
9520fce977Smiod   ARGV0,
9620fce977Smiod   "a",
9720fce977Smiod   0,
9820fce977Smiod 
9920fce977Smiod   /* Test 3 - Check for expansion with only \0 */
10020fce977Smiod   "\b",		/* Test 3 data */
10120fce977Smiod   ARGV0,
10220fce977Smiod   "@test-expandargv-3.lst",
10320fce977Smiod   0,
10420fce977Smiod   ARGV0,
10520fce977Smiod   0,
10620fce977Smiod 
10720fce977Smiod   0 /* Test done marker, don't remove. */
10820fce977Smiod };
10920fce977Smiod 
11020fce977Smiod /* Print a fatal error and exit.  LINE is the line number where we
11120fce977Smiod    detected the error, ERRMSG is the error message to print, and ERR
11220fce977Smiod    is 0 or an errno value to print.  */
11320fce977Smiod 
11420fce977Smiod static void
fatal_error(int line,const char * errmsg,int err)11520fce977Smiod fatal_error (int line, const char *errmsg, int err)
11620fce977Smiod {
11720fce977Smiod   fprintf (stderr, "test-expandargv:%d: %s", line, errmsg);
11820fce977Smiod   if (errno != 0)
11920fce977Smiod     fprintf (stderr, ": %s", xstrerror (err));
12020fce977Smiod   fprintf (stderr, "\n");
12120fce977Smiod   exit (EXIT_FAILURE);
12220fce977Smiod }
12320fce977Smiod 
12420fce977Smiod /* hook_char_replace:
12520fce977Smiod      Replace 'replacethis' with 'withthis' */
12620fce977Smiod 
12720fce977Smiod void
hook_char_replace(char * string,size_t len,char replacethis,char withthis)12820fce977Smiod hook_char_replace (char *string, size_t len, char replacethis, char withthis)
12920fce977Smiod {
13020fce977Smiod   int i = 0;
13120fce977Smiod   for (i = 0; i < len; i++)
13220fce977Smiod     if (string[i] == replacethis)
13320fce977Smiod       string[i] = withthis;
13420fce977Smiod }
13520fce977Smiod 
13620fce977Smiod /* run_replaces:
13720fce977Smiod      Hook here all the character for character replaces.
13820fce977Smiod      Be warned that expanding the string or contracting the string
13920fce977Smiod      should be handled with care. */
14020fce977Smiod 
14120fce977Smiod void
run_replaces(char * string)14220fce977Smiod run_replaces (char * string)
14320fce977Smiod {
14420fce977Smiod   /* Store original string size */
14520fce977Smiod   size_t len = strlen (string);
14620fce977Smiod   hook_char_replace (string, len, '\b', '\0');
14720fce977Smiod }
14820fce977Smiod 
14920fce977Smiod /* write_test:
15020fce977Smiod    Write test datafile */
15120fce977Smiod 
15220fce977Smiod void
writeout_test(int test,const char * test_data)15320fce977Smiod writeout_test (int test, const char * test_data)
15420fce977Smiod {
15520fce977Smiod   char filename[256];
15620fce977Smiod   FILE *fd;
15720fce977Smiod   size_t len;
15820fce977Smiod   char * parse;
15920fce977Smiod 
16020fce977Smiod   /* Unique filename per test */
16120fce977Smiod   sprintf (filename, FILENAME_PATTERN, test);
16220fce977Smiod   fd = fopen (filename, "w");
16320fce977Smiod   if (fd == NULL)
16420fce977Smiod     fatal_error (__LINE__, "Failed to create test file.", errno);
16520fce977Smiod 
16620fce977Smiod   /* Generate RW copy of data for replaces */
16720fce977Smiod   len = strlen (test_data);
16820fce977Smiod   parse = malloc (sizeof (char) * (len + 1));
16920fce977Smiod   if (parse == NULL)
17020fce977Smiod     fatal_error (__LINE__, "Failed to malloc parse.", errno);
17120fce977Smiod 
172*0fb20bf6Sbluhm   memcpy (parse, test_data, sizeof (char) * (len + 1));
17320fce977Smiod   /* Run all possible replaces */
17420fce977Smiod   run_replaces (parse);
17520fce977Smiod 
17620fce977Smiod   fwrite (parse, len, sizeof (char), fd);
17720fce977Smiod   free (parse);
17820fce977Smiod   fclose (fd);
17920fce977Smiod }
18020fce977Smiod 
18120fce977Smiod /* erase_test:
18220fce977Smiod      Erase the test file */
18320fce977Smiod 
18420fce977Smiod void
erase_test(int test)18520fce977Smiod erase_test (int test)
18620fce977Smiod {
18720fce977Smiod   char filename[256];
18820fce977Smiod   sprintf (filename, FILENAME_PATTERN, test);
18920fce977Smiod   if (unlink (filename) != 0)
19020fce977Smiod     fatal_error (__LINE__, "Failed to erase test file.", errno);
19120fce977Smiod }
19220fce977Smiod 
19320fce977Smiod 
19420fce977Smiod /* run_tests:
19520fce977Smiod     Run expandargv
19620fce977Smiod     Compare argv before and after.
19720fce977Smiod     Return number of fails */
19820fce977Smiod 
19920fce977Smiod int
run_tests(const char ** test_data)20020fce977Smiod run_tests (const char **test_data)
20120fce977Smiod {
20220fce977Smiod   int argc_after, argc_before;
20320fce977Smiod   char ** argv_before, ** argv_after;
20420fce977Smiod   int i, j, k, fails, failed;
20520fce977Smiod 
20620fce977Smiod   i = j = fails = 0;
20720fce977Smiod   /* Loop over all the tests */
20820fce977Smiod   while (test_data[j])
20920fce977Smiod     {
21020fce977Smiod       /* Write test data */
21120fce977Smiod       writeout_test (i, test_data[j++]);
21220fce977Smiod       /* Copy argv before */
21320fce977Smiod       argv_before = dupargv ((char **) &test_data[j]);
21420fce977Smiod 
21520fce977Smiod       /* Count argc before/after */
21620fce977Smiod       argc_before = 0;
21720fce977Smiod       argc_after = 0;
21820fce977Smiod       while (test_data[j + argc_before])
21920fce977Smiod         argc_before++;
22020fce977Smiod       j += argc_before + 1; /* Skip null */
22120fce977Smiod       while (test_data[j + argc_after])
22220fce977Smiod         argc_after++;
22320fce977Smiod 
22420fce977Smiod       /* Copy argv after */
22520fce977Smiod       argv_after = dupargv ((char **) &test_data[j]);
22620fce977Smiod 
22720fce977Smiod       /* Run all possible replaces */
22820fce977Smiod       for (k = 0; k < argc_before; k++)
22920fce977Smiod         run_replaces (argv_before[k]);
23020fce977Smiod       for (k = 0; k < argc_after; k++)
23120fce977Smiod         run_replaces (argv_after[k]);
23220fce977Smiod 
23320fce977Smiod       /* Run test: Expand arguments */
23420fce977Smiod       expandargv (&argc_before, &argv_before);
23520fce977Smiod 
23620fce977Smiod       failed = 0;
23720fce977Smiod       /* Compare size first */
23820fce977Smiod       if (argc_before != argc_after)
23920fce977Smiod         {
24020fce977Smiod           printf ("FAIL: test-expandargv-%d. Number of arguments don't match.\n", i);
24120fce977Smiod 	  failed++;
24220fce977Smiod         }
24320fce977Smiod       /* Compare each of the argv's ... */
24420fce977Smiod       else
24520fce977Smiod         for (k = 0; k < argc_after; k++)
24620fce977Smiod           if (strncmp (argv_before[k], argv_after[k], strlen(argv_after[k])) != 0)
24720fce977Smiod             {
24820fce977Smiod               printf ("FAIL: test-expandargv-%d. Arguments don't match.\n", i);
24920fce977Smiod               failed++;
25020fce977Smiod             }
25120fce977Smiod 
25220fce977Smiod       if (!failed)
25320fce977Smiod         printf ("PASS: test-expandargv-%d.\n", i);
25420fce977Smiod       else
25520fce977Smiod         fails++;
25620fce977Smiod 
25720fce977Smiod       freeargv (argv_before);
25820fce977Smiod       freeargv (argv_after);
25920fce977Smiod       /* Advance to next test */
26020fce977Smiod       j += argc_after + 1;
26120fce977Smiod       /* Erase test file */
26220fce977Smiod       erase_test (i);
26320fce977Smiod       i++;
26420fce977Smiod     }
26520fce977Smiod   return fails;
26620fce977Smiod }
26720fce977Smiod 
26820fce977Smiod /* main:
26920fce977Smiod     Run tests.
27020fce977Smiod     Check result and exit with appropriate code. */
27120fce977Smiod 
27220fce977Smiod int
main(int argc,char ** argv)27320fce977Smiod main(int argc, char **argv)
27420fce977Smiod {
27520fce977Smiod   int fails;
27620fce977Smiod   /* Repeat for all the tests:
27720fce977Smiod      - Parse data array and write into file.
27820fce977Smiod        - Run replace hooks before writing to file.
27920fce977Smiod      - Parse data array and build argv before/after.
28020fce977Smiod        - Run replace hooks on argv before/after
28120fce977Smiod      - Run expandargv.
28220fce977Smiod      - Compare output of expandargv argv to after argv.
28320fce977Smiod        - If they compare the same then test passes
28420fce977Smiod          else the test fails.
28520fce977Smiod      - Erase test file. */
28620fce977Smiod 
28720fce977Smiod   fails = run_tests (test_data);
28820fce977Smiod   if (!fails)
28920fce977Smiod     exit (EXIT_SUCCESS);
29020fce977Smiod   else
29120fce977Smiod     exit (EXIT_FAILURE);
29220fce977Smiod }
29320fce977Smiod 
294