OSDN Git Service

2009-10-08 Daniel Gutson <dgutson@codesourcery.com>
[pf3gnuchains/gcc-fork.git] / libiberty / testsuite / test-expandargv.c
1 /* expandargv test program,
2    Copyright (C) 2006 Free Software Foundation, Inc.
3    Written by Carlos O'Donell <carlos@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
44 #ifndef EXIT_SUCCESS
45 #define EXIT_SUCCESS 0
46 #endif
47
48 #ifndef EXIT_FAILURE
49 #define EXIT_FAILURE 1
50 #endif
51
52 static void fatal_error (int, const char *, int) ATTRIBUTE_NORETURN;
53 void writeout_test (int, const char *);
54 void run_replaces (char *);
55 void hook_char_replace (char *, size_t, char, char);
56 int run_tests (const char **);
57 void erase_test (int);
58
59 /* Test input data, argv before, and argv after:
60  
61    The \n is an important part of test_data since expandargv
62    may have to work in environments where \n is translated
63    as \r\n. Thus \n is included in the test data for the file. 
64
65    We use \b to indicate that the test data is the null character.
66    This is because we use \0 normally to represent the end of the 
67    file data, so we need something else for this. */
68
69 #define FILENAME_PATTERN "test-expandargv-%d.lst"
70 #define ARGV0 "test-expandargv"
71
72 const char *test_data[] = {
73   /* Test 0 - Check for expansion with \r\n */
74   "a\r\nb",     /* Test 0 data */
75   ARGV0,
76   "@test-expandargv-0.lst",
77   0, /* End of argv[] before expansion */
78   ARGV0,
79   "a",
80   "b",
81   0, /* End of argv[] after expansion */
82
83   /* Test 1 - Check for expansion with \n */
84   "a\nb",       /* Test 1 data */
85   ARGV0,
86   "@test-expandargv-1.lst",
87   0,
88   ARGV0,
89   "a",
90   "b",
91   0,
92
93   /* Test 2 - Check for expansion with \0 */
94   "a\bb",       /* Test 2 data */
95   ARGV0,
96   "@test-expandargv-2.lst",
97   0,
98   ARGV0,
99   "a",
100   0,
101
102   /* Test 3 - Check for expansion with only \0 */
103   "\b",         /* Test 3 data */
104   ARGV0,
105   "@test-expandargv-3.lst",
106   0,
107   ARGV0,
108   0,
109
110   /* Test 4 - Check for options beginning with an empty line.  */
111   "\na\nb",     /* Test 4 data */
112   ARGV0,
113   "@test-expandargv-4.lst",
114   0,
115   ARGV0,
116   "a",
117   "b",
118   0,
119
120   /* Test 5 - Check for options containing an empty argument.  */
121   "a\n''\nb",    /* Test 5 data */
122   ARGV0,
123   "@test-expandargv-5.lst",
124   0,
125   ARGV0,
126   "a",
127   "",
128   "b",
129   0,
130
131   /* Test 6 - Check for options containing a quoted newline.  */
132   "a\n'a\n\nb'\nb",    /* Test 6 data */
133   ARGV0,
134   "@test-expandargv-6.lst",
135   0,
136   ARGV0,
137   "a",
138   "a\n\nb",
139   "b",
140   0,
141
142   0 /* Test done marker, don't remove. */
143 };
144
145 /* Print a fatal error and exit.  LINE is the line number where we
146    detected the error, ERRMSG is the error message to print, and ERR
147    is 0 or an errno value to print.  */
148
149 static void
150 fatal_error (int line, const char *errmsg, int err)
151 {
152   fprintf (stderr, "test-expandargv:%d: %s", line, errmsg);
153   if (errno != 0)
154     fprintf (stderr, ": %s", xstrerror (err));
155   fprintf (stderr, "\n");
156   exit (EXIT_FAILURE);
157 }
158
159 /* hook_char_replace:
160      Replace 'replacethis' with 'withthis' */
161
162 void
163 hook_char_replace (char *string, size_t len, char replacethis, char withthis)
164 {
165   int i = 0;
166   for (i = 0; i < len; i++)
167     if (string[i] == replacethis)
168       string[i] = withthis;
169 }
170
171 /* run_replaces:
172      Hook here all the character for character replaces.
173      Be warned that expanding the string or contracting the string
174      should be handled with care. */
175
176 void
177 run_replaces (char * string)
178 {
179   /* Store original string size */
180   size_t len = strlen (string);
181   hook_char_replace (string, len, '\b', '\0');
182 }
183
184 /* write_test:
185    Write test datafile */
186
187 void
188 writeout_test (int test, const char * test_data)
189 {
190   char filename[256];
191   FILE *fd;
192   size_t len;
193   char * parse;
194
195   /* Unique filename per test */
196   sprintf (filename, FILENAME_PATTERN, test);
197   fd = fopen (filename, "w");
198   if (fd == NULL)
199     fatal_error (__LINE__, "Failed to create test file.", errno);
200
201   /* Generate RW copy of data for replaces */
202   len = strlen (test_data);
203   parse = malloc (sizeof (char) * (len + 1));
204   if (parse == NULL)
205     fatal_error (__LINE__, "Failed to malloc parse.", errno);
206       
207   memcpy (parse, test_data, sizeof (char) * len);
208   /* Run all possible replaces */
209   run_replaces (parse);
210
211   fwrite (parse, len, sizeof (char), fd);
212   free (parse);
213   fclose (fd);
214 }
215
216 /* erase_test:
217      Erase the test file */
218
219 void 
220 erase_test (int test)
221 {
222   char filename[256]; 
223   sprintf (filename, FILENAME_PATTERN, test);
224   if (unlink (filename) != 0)
225     fatal_error (__LINE__, "Failed to erase test file.", errno);
226 }
227
228
229 /* run_tests:
230     Run expandargv
231     Compare argv before and after.
232     Return number of fails */
233
234 int
235 run_tests (const char **test_data)
236 {
237   int argc_after, argc_before;
238   char ** argv_before, ** argv_after;
239   int i, j, k, fails, failed;
240
241   i = j = fails = 0;
242   /* Loop over all the tests */
243   while (test_data[j])
244     {
245       /* Write test data */
246       writeout_test (i, test_data[j++]);
247       /* Copy argv before */
248       argv_before = dupargv ((char **) &test_data[j]);
249
250       /* Count argc before/after */
251       argc_before = 0;
252       argc_after = 0;
253       while (test_data[j + argc_before])
254         argc_before++;
255       j += argc_before + 1; /* Skip null */
256       while (test_data[j + argc_after])
257         argc_after++;
258
259       /* Copy argv after */
260       argv_after = dupargv ((char **) &test_data[j]);
261
262       /* Run all possible replaces */
263       for (k = 0; k < argc_before; k++)
264         run_replaces (argv_before[k]);
265       for (k = 0; k < argc_after; k++)
266         run_replaces (argv_after[k]);
267
268       /* Run test: Expand arguments */
269       expandargv (&argc_before, &argv_before);
270
271       failed = 0;
272       /* Compare size first */
273       if (argc_before != argc_after)
274         {
275           printf ("FAIL: test-expandargv-%d. Number of arguments don't match.\n", i);
276           failed++;
277         }
278       /* Compare each of the argv's ... */
279       else
280         for (k = 0; k < argc_after; k++)
281           if (strcmp (argv_before[k], argv_after[k]) != 0)
282             {
283               printf ("FAIL: test-expandargv-%d. Arguments don't match.\n", i);
284               failed++;
285             }
286
287       if (!failed)
288         printf ("PASS: test-expandargv-%d.\n", i);
289       else
290         fails++;
291
292       freeargv (argv_before);
293       freeargv (argv_after);
294       /* Advance to next test */
295       j += argc_after + 1;
296       /* Erase test file */
297       erase_test (i);
298       i++;
299     }
300   return fails;
301 }
302
303 /* main:
304     Run tests. 
305     Check result and exit with appropriate code. */
306
307 int 
308 main(int argc, char **argv)
309 {
310   int fails;
311   /* Repeat for all the tests:
312      - Parse data array and write into file.
313        - Run replace hooks before writing to file.
314      - Parse data array and build argv before/after.
315        - Run replace hooks on argv before/after
316      - Run expandargv.
317      - Compare output of expandargv argv to after argv.
318        - If they compare the same then test passes
319          else the test fails. 
320      - Erase test file. */
321
322   fails = run_tests (test_data);
323   if (!fails)
324     exit (EXIT_SUCCESS);
325   else
326     exit (EXIT_FAILURE);
327 }
328