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